From f8af5cf600354830d4ccf59732403f0f073eccb9 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 22 Dec 2013 00:04:03 +0000 Subject: Vendor import of llvm release_34 branch r197841 (effectively, 3.4 RC3): https://llvm.org/svn/llvm-project/llvm/branches/release_34@197841 --- .clang-format | 1 + CMakeLists.txt | 144 +- CODE_OWNERS.TXT | 20 +- CREDITS.TXT | 18 +- LICENSE.TXT | 1 + LLVMBuild.txt | 2 +- Makefile | 16 +- Makefile.config.in | 3 + Makefile.rules | 362 +- autoconf/config.guess | 3 + autoconf/configure.ac | 151 +- autoconf/m4/libtool.m4 | 2 +- autoconf/m4/link_options.m4 | 9 +- autoconf/m4/ltdl.m4 | 25 +- bindings/ocaml/Makefile | 3 +- bindings/ocaml/Makefile.ocaml | 86 +- bindings/ocaml/analysis/analysis_ocaml.c | 4 +- bindings/ocaml/analysis/llvm_analysis.ml | 2 +- bindings/ocaml/analysis/llvm_analysis.mli | 4 +- bindings/ocaml/backends/META.llvm_backend.in | 8 + bindings/ocaml/backends/Makefile | 61 + bindings/ocaml/backends/Makefile.common | 65 + bindings/ocaml/backends/backend_ocaml.c | 37 + bindings/ocaml/backends/llvm_backend.ml.in | 10 + bindings/ocaml/backends/llvm_backend.mli.in | 19 + bindings/ocaml/bitreader/bitreader_ocaml.c | 4 +- bindings/ocaml/bitreader/llvm_bitreader.ml | 2 +- bindings/ocaml/bitreader/llvm_bitreader.mli | 4 +- bindings/ocaml/bitwriter/bitwriter_ocaml.c | 4 +- bindings/ocaml/bitwriter/llvm_bitwriter.ml | 4 +- bindings/ocaml/bitwriter/llvm_bitwriter.mli | 4 +- .../ocaml/executionengine/executionengine_ocaml.c | 19 +- .../ocaml/executionengine/llvm_executionengine.ml | 7 +- .../ocaml/executionengine/llvm_executionengine.mli | 19 +- bindings/ocaml/irreader/Makefile | 19 + bindings/ocaml/irreader/irreader_ocaml.c | 59 + bindings/ocaml/irreader/llvm_irreader.ml | 17 + bindings/ocaml/irreader/llvm_irreader.mli | 21 + bindings/ocaml/linker/Makefile | 19 + bindings/ocaml/linker/linker_ocaml.c | 54 + bindings/ocaml/linker/llvm_linker.ml | 22 + bindings/ocaml/linker/llvm_linker.mli | 26 + bindings/ocaml/llvm/META.llvm.in | 32 + bindings/ocaml/llvm/Makefile | 2 +- bindings/ocaml/llvm/llvm.ml | 153 +- bindings/ocaml/llvm/llvm.mli | 402 +- bindings/ocaml/llvm/llvm_ocaml.c | 234 +- bindings/ocaml/target/llvm_target.ml | 146 +- bindings/ocaml/target/llvm_target.mli | 265 +- bindings/ocaml/target/target_ocaml.c | 384 +- bindings/ocaml/transforms/Makefile | 2 +- bindings/ocaml/transforms/ipo/Makefile | 1 - bindings/ocaml/transforms/ipo/ipo_ocaml.c | 10 +- bindings/ocaml/transforms/ipo/llvm_ipo.ml | 34 +- bindings/ocaml/transforms/ipo/llvm_ipo.mli | 10 +- bindings/ocaml/transforms/passmgr_builder/Makefile | 19 + .../passmgr_builder/llvm_passmgr_builder.ml | 32 + .../passmgr_builder/llvm_passmgr_builder.mli | 54 + .../passmgr_builder/passmgr_builder_ocaml.c | 113 + bindings/ocaml/transforms/scalar/Makefile | 1 - .../ocaml/transforms/scalar/llvm_scalar_opts.ml | 5 +- .../ocaml/transforms/scalar/llvm_scalar_opts.mli | 8 +- .../ocaml/transforms/scalar/scalar_opts_ocaml.c | 10 +- bindings/ocaml/transforms/vectorize/Makefile | 19 + .../ocaml/transforms/vectorize/llvm_vectorize.ml | 15 + .../ocaml/transforms/vectorize/llvm_vectorize.mli | 25 + .../ocaml/transforms/vectorize/vectorize_ocaml.c | 38 + bindings/python/llvm/bit_reader.py | 31 + bindings/python/llvm/common.py | 2 +- bindings/python/llvm/core.py | 442 + bindings/python/llvm/disassembler.py | 29 +- bindings/python/llvm/tests/base.py | 6 + bindings/python/llvm/tests/test.bc | Bin 0 -> 1344 bytes bindings/python/llvm/tests/test_bitreader.py | 15 + bindings/python/llvm/tests/test_core.py | 109 +- bindings/python/llvm/tests/test_disassembler.py | 4 + bindings/python/llvm/tests/test_file | 1 + cmake/config-ix.cmake | 125 +- cmake/modules/AddLLVM.cmake | 81 +- cmake/modules/CMakeLists.txt | 32 +- cmake/modules/ChooseMSVCCRT.cmake | 2 +- cmake/modules/HandleLLVMOptions.cmake | 61 +- cmake/modules/LLVM-Config.cmake | 7 +- cmake/modules/LLVMConfig.cmake.in | 4 + cmake/modules/TableGen.cmake | 19 +- cmake/nsis_logo.bmp | Bin 0 -> 30776 bytes cmake/platforms/Android.cmake | 11 +- configure | 1243 +- docs/Atomics.rst | 2 +- docs/BitCodeFormat.rst | 5 +- docs/CMake.rst | 12 +- docs/CMakeLists.txt | 51 + docs/CodeGenerator.rst | 25 +- docs/CodingStandards.rst | 4 +- docs/CommandGuide/FileCheck.rst | 145 +- docs/CommandGuide/index.rst | 1 - docs/CommandGuide/lit.rst | 15 +- docs/CommandGuide/llc.rst | 18 +- docs/CommandGuide/llvm-ar.rst | 129 +- docs/CommandGuide/llvm-extract.rst | 65 +- docs/CommandGuide/llvm-nm.rst | 61 +- docs/CommandGuide/llvm-ranlib.rst | 61 - docs/CommandGuide/llvm-symbolizer.rst | 16 + docs/CommandLine.rst | 5 +- docs/CompilerWriterInfo.rst | 30 +- docs/DeveloperPolicy.rst | 26 +- docs/ExtendingLLVM.rst | 4 +- docs/Extensions.rst | 108 +- docs/GarbageCollection.rst | 128 +- docs/GettingStarted.rst | 27 +- docs/GettingStartedVS.rst | 6 +- docs/GoldPlugin.rst | 36 +- docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt | 2 +- docs/HowToBuildOnARM.rst | 38 +- docs/HowToCrossCompileLLVM.rst | 175 + docs/HowToReleaseLLVM.rst | 3 + docs/LangRef.rst | 643 +- docs/MCJIT-creation.png | Bin 0 -> 26456 bytes docs/MCJIT-dyld-load.png | Bin 0 -> 38960 bytes docs/MCJIT-engine-builder.png | Bin 0 -> 18731 bytes docs/MCJIT-load-object.png | Bin 0 -> 76467 bytes docs/MCJIT-load.png | Bin 0 -> 27365 bytes docs/MCJIT-resolve-relocations.png | Bin 0 -> 57621 bytes docs/MCJITDesignAndImplementation.rst | 180 + docs/Makefile | 15 +- docs/MakefileGuide.rst | 49 +- docs/NVPTXUsage.rst | 704 + docs/Passes.rst | 10 +- docs/Phabricator.rst | 4 +- docs/ProgrammersManual.rst | 22 +- docs/ReleaseNotes.rst | 383 +- docs/ReleaseProcess.rst | 212 + docs/SourceLevelDebugging.rst | 448 +- docs/TestingGuide.rst | 74 +- docs/Vectorizers.rst | 48 +- docs/WritingAnLLVMBackend.rst | 103 +- docs/WritingAnLLVMPass.rst | 8 +- docs/YamlIO.rst | 28 +- docs/conf.py | 4 +- docs/doxygen.cfg.in | 13 +- docs/index.rst | 12 + docs/tutorial/LangImpl2.rst | 402 +- docs/tutorial/LangImpl3.rst | 570 +- docs/tutorial/LangImpl4.rst | 620 +- docs/tutorial/LangImpl5.rst | 862 +- docs/tutorial/LangImpl6.rst | 980 +- docs/tutorial/LangImpl7.rst | 1147 +- docs/tutorial/OCamlLangImpl2.rst | 3 + docs/tutorial/index.rst | 2 +- docs/yaml2obj.rst | 2 +- examples/BrainF/BrainFDriver.cpp | 2 +- examples/ExceptionDemo/ExceptionDemo.cpp | 13 +- examples/ExceptionDemo/Makefile | 2 +- examples/Kaleidoscope/Chapter2/toy.cpp | 19 +- examples/Kaleidoscope/Chapter3/toy.cpp | 4 +- examples/Kaleidoscope/Chapter4/toy.cpp | 4 +- examples/Kaleidoscope/Chapter5/toy.cpp | 4 +- examples/Kaleidoscope/Chapter6/toy.cpp | 4 +- examples/Kaleidoscope/Chapter7/toy.cpp | 4 +- examples/Kaleidoscope/MCJIT/README.txt | 12 + examples/Kaleidoscope/MCJIT/cached/Makefile | 11 + examples/Kaleidoscope/MCJIT/cached/README.txt | 28 + examples/Kaleidoscope/MCJIT/cached/genk-timing.py | 219 + examples/Kaleidoscope/MCJIT/cached/split-lib.py | 70 + examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp | 1208 + examples/Kaleidoscope/MCJIT/cached/toy.cpp | 1552 ++ examples/Kaleidoscope/MCJIT/complete/Makefile | 4 + examples/Kaleidoscope/MCJIT/complete/README.txt | 25 + .../Kaleidoscope/MCJIT/complete/genk-timing.py | 224 + examples/Kaleidoscope/MCJIT/complete/split-lib.py | 70 + examples/Kaleidoscope/MCJIT/complete/toy.cpp | 1711 ++ examples/Kaleidoscope/MCJIT/initial/Makefile | 4 + examples/Kaleidoscope/MCJIT/initial/README.txt | 18 + examples/Kaleidoscope/MCJIT/initial/toy.cpp | 1382 + examples/Kaleidoscope/MCJIT/lazy/Makefile | 7 + examples/Kaleidoscope/MCJIT/lazy/README.txt | 25 + examples/Kaleidoscope/MCJIT/lazy/genk-timing.py | 219 + examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp | 1168 + examples/Kaleidoscope/MCJIT/lazy/toy.cpp | 1423 ++ include/llvm-c/BitReader.h | 4 +- include/llvm-c/BitWriter.h | 4 +- include/llvm-c/Core.h | 174 +- include/llvm-c/Disassembler.h | 19 +- include/llvm-c/ExecutionEngine.h | 36 +- include/llvm-c/IRReader.h | 40 + include/llvm-c/LinkTimeOptimizer.h | 4 +- include/llvm-c/Object.h | 1 - include/llvm-c/Support.h | 35 + include/llvm-c/Target.h | 108 +- include/llvm-c/TargetMachine.h | 28 +- include/llvm-c/Transforms/Scalar.h | 6 + include/llvm-c/lto.h | 42 +- include/llvm/ADT/APFloat.h | 998 +- include/llvm/ADT/APInt.h | 1483 +- include/llvm/ADT/APSInt.h | 12 +- include/llvm/ADT/ArrayRef.h | 14 +- include/llvm/ADT/BitVector.h | 23 +- include/llvm/ADT/DenseMap.h | 17 +- include/llvm/ADT/FoldingSet.h | 5 +- include/llvm/ADT/ImmutableMap.h | 1 + include/llvm/ADT/ImmutableSet.h | 13 + include/llvm/ADT/IntervalMap.h | 6 +- include/llvm/ADT/NullablePtr.h | 52 - include/llvm/ADT/OwningPtr.h | 5 +- include/llvm/ADT/PointerIntPair.h | 3 +- include/llvm/ADT/PointerUnion.h | 23 +- include/llvm/ADT/STLExtras.h | 28 +- include/llvm/ADT/SetVector.h | 2 +- include/llvm/ADT/SmallBitVector.h | 42 +- include/llvm/ADT/SmallPtrSet.h | 2 +- include/llvm/ADT/SmallVector.h | 4 +- include/llvm/ADT/SparseBitVector.h | 12 +- include/llvm/ADT/StringExtras.h | 43 + include/llvm/ADT/StringMap.h | 11 + include/llvm/ADT/StringRef.h | 14 +- include/llvm/ADT/Triple.h | 38 +- include/llvm/ADT/ilist.h | 6 +- include/llvm/ADT/polymorphic_ptr.h | 117 + include/llvm/Analysis/AliasAnalysis.h | 4 + include/llvm/Analysis/BlockFrequencyImpl.h | 117 +- include/llvm/Analysis/BlockFrequencyInfo.h | 12 +- include/llvm/Analysis/BranchProbabilityInfo.h | 4 + include/llvm/Analysis/CFG.h | 83 + include/llvm/Analysis/CFGPrinter.h | 31 +- include/llvm/Analysis/CallGraph.h | 73 +- include/llvm/Analysis/ConstantFolding.h | 6 +- include/llvm/Analysis/DependenceAnalysis.h | 42 +- include/llvm/Analysis/Dominators.h | 20 + include/llvm/Analysis/InlineCost.h | 3 +- include/llvm/Analysis/InstructionSimplify.h | 2 +- include/llvm/Analysis/LoopInfo.h | 35 +- include/llvm/Analysis/LoopInfoImpl.h | 41 +- include/llvm/Analysis/LoopPass.h | 2 +- include/llvm/Analysis/MemoryBuiltins.h | 35 +- include/llvm/Analysis/Passes.h | 65 +- include/llvm/Analysis/PathNumbering.h | 304 - include/llvm/Analysis/PathProfileInfo.h | 112 - include/llvm/Analysis/PostDominators.h | 5 + include/llvm/Analysis/ProfileDataLoader.h | 140 - include/llvm/Analysis/ProfileDataTypes.h | 39 - include/llvm/Analysis/ProfileInfo.h | 247 - include/llvm/Analysis/ProfileInfoLoader.h | 81 - include/llvm/Analysis/ProfileInfoTypes.h | 52 - include/llvm/Analysis/RegionPass.h | 4 +- include/llvm/Analysis/ScalarEvolution.h | 67 +- include/llvm/Analysis/ScalarEvolutionExpander.h | 4 +- include/llvm/Analysis/ScalarEvolutionExpressions.h | 148 +- include/llvm/Analysis/TargetTransformInfo.h | 75 +- include/llvm/Analysis/ValueTracking.h | 3 +- include/llvm/AutoUpgrade.h | 40 +- include/llvm/Bitcode/Archive.h | 538 - include/llvm/Bitcode/BitstreamReader.h | 5 +- include/llvm/Bitcode/BitstreamWriter.h | 3 +- include/llvm/Bitcode/LLVMBitCodes.h | 45 +- include/llvm/CodeGen/Analysis.h | 9 + include/llvm/CodeGen/AsmPrinter.h | 52 +- include/llvm/CodeGen/CalcSpillWeights.h | 51 +- include/llvm/CodeGen/CallingConvLower.h | 4 +- include/llvm/CodeGen/CommandFlags.h | 16 +- include/llvm/CodeGen/FastISel.h | 284 +- include/llvm/CodeGen/FunctionLoweringInfo.h | 9 +- include/llvm/CodeGen/ISDOpcodes.h | 28 +- include/llvm/CodeGen/LexicalScopes.h | 18 +- include/llvm/CodeGen/LiveInterval.h | 605 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 81 +- include/llvm/CodeGen/LiveIntervalUnion.h | 2 +- include/llvm/CodeGen/LiveRangeEdit.h | 44 +- include/llvm/CodeGen/LiveRegUnits.h | 88 + include/llvm/CodeGen/LiveVariables.h | 4 +- include/llvm/CodeGen/MachineBasicBlock.h | 34 +- .../llvm/CodeGen/MachineBranchProbabilityInfo.h | 2 +- include/llvm/CodeGen/MachineConstantPool.h | 10 +- include/llvm/CodeGen/MachineFrameInfo.h | 13 +- include/llvm/CodeGen/MachineInstr.h | 21 +- include/llvm/CodeGen/MachineInstrBuilder.h | 45 + include/llvm/CodeGen/MachineModuleInfo.h | 16 +- include/llvm/CodeGen/MachineOperand.h | 4 +- include/llvm/CodeGen/MachineRegisterInfo.h | 95 +- include/llvm/CodeGen/MachineRelocation.h | 2 +- include/llvm/CodeGen/MachineScheduler.h | 135 +- include/llvm/CodeGen/PBQP/Graph.h | 418 +- include/llvm/CodeGen/PBQP/HeuristicBase.h | 62 +- include/llvm/CodeGen/PBQP/HeuristicSolver.h | 296 +- include/llvm/CodeGen/PBQP/Heuristics/Briggs.h | 210 +- include/llvm/CodeGen/PBQP/Solution.h | 19 +- include/llvm/CodeGen/Passes.h | 60 +- include/llvm/CodeGen/PseudoSourceValue.h | 2 +- include/llvm/CodeGen/RegAllocPBQP.h | 23 +- include/llvm/CodeGen/RegisterClassInfo.h | 15 +- include/llvm/CodeGen/RegisterPressure.h | 168 +- include/llvm/CodeGen/RegisterScavenging.h | 4 +- include/llvm/CodeGen/RuntimeLibcalls.h | 38 +- include/llvm/CodeGen/ScheduleDAG.h | 33 +- include/llvm/CodeGen/ScheduleDAGInstrs.h | 35 +- include/llvm/CodeGen/SelectionDAG.h | 308 +- include/llvm/CodeGen/SelectionDAGISel.h | 12 +- include/llvm/CodeGen/SelectionDAGNodes.h | 276 +- include/llvm/CodeGen/SlotIndexes.h | 13 +- include/llvm/CodeGen/StackMaps.h | 175 + include/llvm/CodeGen/StackProtector.h | 127 + include/llvm/CodeGen/TargetSchedule.h | 36 +- include/llvm/CodeGen/ValueTypes.h | 115 +- include/llvm/CodeGen/ValueTypes.td | 75 +- include/llvm/Config/config.h.cmake | 122 +- include/llvm/Config/config.h.in | 101 +- include/llvm/Config/llvm-config.h.cmake | 3 - include/llvm/Config/llvm-config.h.in | 3 - include/llvm/DIBuilder.h | 186 +- include/llvm/DebugInfo.h | 1575 +- include/llvm/DebugInfo/DIContext.h | 23 +- include/llvm/DebugInfo/DWARFFormValue.h | 67 +- include/llvm/ExecutionEngine/ExecutionEngine.h | 153 +- include/llvm/ExecutionEngine/JITMemoryManager.h | 16 - include/llvm/ExecutionEngine/ObjectBuffer.h | 3 + include/llvm/ExecutionEngine/ObjectCache.h | 25 +- include/llvm/ExecutionEngine/ObjectImage.h | 1 + include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 112 + include/llvm/ExecutionEngine/RuntimeDyld.h | 62 +- .../llvm/ExecutionEngine/SectionMemoryManager.h | 90 +- include/llvm/GVMaterializer.h | 12 +- include/llvm/IR/Argument.h | 5 + include/llvm/IR/Attributes.h | 9 +- include/llvm/IR/CallingConv.h | 25 +- include/llvm/IR/Constants.h | 17 +- include/llvm/IR/DataLayout.h | 34 +- include/llvm/IR/Function.h | 61 +- include/llvm/IR/GlobalAlias.h | 15 +- include/llvm/IR/GlobalValue.h | 21 +- include/llvm/IR/GlobalVariable.h | 4 +- include/llvm/IR/IRBuilder.h | 139 +- include/llvm/IR/InlineAsm.h | 2 +- include/llvm/IR/InstrTypes.h | 20 +- include/llvm/IR/Instruction.def | 35 +- include/llvm/IR/Instructions.h | 481 +- include/llvm/IR/Intrinsics.h | 2 +- include/llvm/IR/Intrinsics.td | 48 +- include/llvm/IR/IntrinsicsAArch64.td | 388 + include/llvm/IR/IntrinsicsARM.td | 81 +- include/llvm/IR/IntrinsicsMips.td | 1368 + include/llvm/IR/IntrinsicsNVVM.td | 2 - include/llvm/IR/IntrinsicsPowerPC.td | 5 + include/llvm/IR/IntrinsicsX86.td | 553 +- include/llvm/IR/IntrinsicsXCore.td | 12 +- include/llvm/IR/LLVMContext.h | 22 +- include/llvm/IR/LegacyPassManager.h | 111 + include/llvm/IR/LegacyPassManagers.h | 470 + include/llvm/IR/Metadata.h | 12 +- include/llvm/IR/Module.h | 23 +- include/llvm/IR/Operator.h | 4 +- include/llvm/IR/PassManager.h | 383 + include/llvm/IR/Type.h | 8 + include/llvm/IR/TypeBuilder.h | 2 +- include/llvm/IR/Use.h | 1 - include/llvm/IR/Value.h | 75 +- include/llvm/InitializePasses.h | 27 +- include/llvm/InstVisitor.h | 1 + include/llvm/LTO/LTOCodeGenerator.h | 153 + include/llvm/LTO/LTOModule.h | 196 + include/llvm/LinkAllPasses.h | 15 +- include/llvm/Linker.h | 2 + include/llvm/MC/MCAsmBackend.h | 20 +- include/llvm/MC/MCAsmInfo.h | 111 +- include/llvm/MC/MCAsmInfoELF.h | 23 + include/llvm/MC/MCAssembler.h | 21 + include/llvm/MC/MCAtom.h | 183 +- include/llvm/MC/MCCodeGenInfo.h | 3 + include/llvm/MC/MCContext.h | 34 +- include/llvm/MC/MCDisassembler.h | 39 +- include/llvm/MC/MCDwarf.h | 766 +- include/llvm/MC/MCELFObjectWriter.h | 14 - include/llvm/MC/MCELFStreamer.h | 42 +- include/llvm/MC/MCELFSymbolFlags.h | 2 +- include/llvm/MC/MCExpr.h | 66 +- include/llvm/MC/MCExternalSymbolizer.h | 58 + include/llvm/MC/MCFunction.h | 142 + include/llvm/MC/MCInstPrinter.h | 28 +- include/llvm/MC/MCInstrAnalysis.h | 11 +- include/llvm/MC/MCInstrDesc.h | 35 +- include/llvm/MC/MCInstrItineraries.h | 10 +- include/llvm/MC/MCMachOSymbolFlags.h | 6 +- include/llvm/MC/MCMachObjectWriter.h | 11 +- include/llvm/MC/MCModule.h | 117 +- include/llvm/MC/MCModuleYAML.h | 41 + include/llvm/MC/MCObjectDisassembler.h | 175 + include/llvm/MC/MCObjectFileInfo.h | 14 + include/llvm/MC/MCObjectStreamer.h | 28 +- include/llvm/MC/MCObjectSymbolizer.h | 81 + include/llvm/MC/MCParser/AsmLexer.h | 1 + include/llvm/MC/MCParser/MCAsmParser.h | 2 +- include/llvm/MC/MCRegisterInfo.h | 130 +- include/llvm/MC/MCRelocationInfo.h | 55 + include/llvm/MC/MCSchedule.h | 81 +- include/llvm/MC/MCSectionCOFF.h | 36 +- include/llvm/MC/MCSectionMachO.h | 2 +- include/llvm/MC/MCStreamer.h | 1341 +- include/llvm/MC/MCSubtargetInfo.h | 3 + include/llvm/MC/MCSymbolizer.h | 81 + include/llvm/MC/MCTargetAsmParser.h | 11 +- include/llvm/MC/MCWinCOFFObjectWriter.h | 1 + include/llvm/MC/MachineLocation.h | 37 +- include/llvm/MC/SubtargetFeature.h | 15 +- include/llvm/Object/Archive.h | 109 +- include/llvm/Object/Binary.h | 5 + include/llvm/Object/COFF.h | 186 +- include/llvm/Object/COFFYAML.h | 141 + include/llvm/Object/ELF.h | 2914 +-- include/llvm/Object/ELFObjectFile.h | 1027 + include/llvm/Object/ELFTypes.h | 463 + include/llvm/Object/ELFYAML.h | 163 + include/llvm/Object/Error.h | 25 +- include/llvm/Object/MachO.h | 171 +- include/llvm/Object/MachOFormat.h | 415 - include/llvm/Object/MachOUniversal.h | 102 + include/llvm/Object/ObjectFile.h | 60 +- include/llvm/Object/RelocVisitor.h | 88 +- include/llvm/Object/YAML.h | 116 + include/llvm/Option/ArgList.h | 9 + include/llvm/Option/OptParser.td | 8 +- include/llvm/Option/OptTable.h | 32 +- include/llvm/Option/Option.h | 18 +- include/llvm/PassManager.h | 104 +- include/llvm/PassManagers.h | 470 - include/llvm/Support/Allocator.h | 15 +- include/llvm/Support/BlockFrequency.h | 26 +- include/llvm/Support/CFG.h | 8 +- include/llvm/Support/COFF.h | 30 +- include/llvm/Support/CallSite.h | 17 +- include/llvm/Support/Casting.h | 27 +- include/llvm/Support/CommandLine.h | 61 +- include/llvm/Support/Compiler.h | 82 +- include/llvm/Support/Compression.h | 2 + include/llvm/Support/ConstantRange.h | 12 +- include/llvm/Support/ConvertUTF.h | 24 +- include/llvm/Support/DataTypes.h.cmake | 9 +- include/llvm/Support/DataTypes.h.in | 10 +- include/llvm/Support/Debug.h | 4 +- include/llvm/Support/DebugLoc.h | 4 +- include/llvm/Support/Dwarf.h | 252 +- include/llvm/Support/ELF.h | 289 +- include/llvm/Support/ErrorOr.h | 266 +- include/llvm/Support/FileSystem.h | 390 +- include/llvm/Support/FileUtilities.h | 4 +- include/llvm/Support/FormattedStream.h | 47 +- include/llvm/Support/GCOV.h | 105 +- include/llvm/Support/GetElementPtrTypeIterator.h | 2 +- include/llvm/Support/GraphWriter.h | 44 +- include/llvm/Support/Host.h | 4 +- include/llvm/Support/IntegersSubset.h | 540 - include/llvm/Support/IntegersSubsetMapping.h | 588 - include/llvm/Support/LEB128.h | 18 +- include/llvm/Support/MD5.h | 71 + include/llvm/Support/MachO.h | 823 +- include/llvm/Support/ManagedStatic.h | 1 - include/llvm/Support/MathExtras.h | 361 +- include/llvm/Support/MemoryBuffer.h | 31 +- include/llvm/Support/MemoryObject.h | 11 +- include/llvm/Support/PassNameParser.h | 13 +- include/llvm/Support/Path.h | 381 +- include/llvm/Support/PathV1.h | 743 - include/llvm/Support/PathV2.h | 381 - include/llvm/Support/PatternMatch.h | 21 +- include/llvm/Support/PrettyStackTrace.h | 10 +- include/llvm/Support/Process.h | 40 +- include/llvm/Support/Program.h | 212 +- include/llvm/Support/RecyclingAllocator.h | 8 +- include/llvm/Support/Regex.h | 4 + include/llvm/Support/Registry.h | 2 + include/llvm/Support/Signals.h | 4 +- include/llvm/Support/Solaris.h | 9 + include/llvm/Support/SourceMgr.h | 22 +- include/llvm/Support/StreamableMemoryObject.h | 18 +- include/llvm/Support/StringRefMemoryObject.h | 41 + include/llvm/Support/SystemUtils.h | 10 - include/llvm/Support/TargetRegistry.h | 242 +- include/llvm/Support/TimeValue.h | 5 +- include/llvm/Support/ToolOutputFile.h | 4 +- include/llvm/Support/Unicode.h | 62 + include/llvm/Support/UnicodeCharRanges.h | 96 + include/llvm/Support/Valgrind.h | 4 +- include/llvm/Support/ValueHandle.h | 5 +- include/llvm/Support/YAMLParser.h | 84 +- include/llvm/Support/YAMLTraits.h | 56 +- include/llvm/Support/raw_ostream.h | 19 +- include/llvm/TableGen/Record.h | 82 +- include/llvm/TableGen/StringToOffsetTable.h | 83 + include/llvm/TableGen/TableGenBackend.h | 2 +- include/llvm/Target/CostTable.h | 35 +- include/llvm/Target/Mangler.h | 23 +- include/llvm/Target/Target.td | 63 +- include/llvm/Target/TargetCallingConv.h | 8 +- include/llvm/Target/TargetCallingConv.td | 6 + include/llvm/Target/TargetFrameLowering.h | 5 + include/llvm/Target/TargetInstrInfo.h | 73 +- include/llvm/Target/TargetLibraryInfo.h | 31 +- include/llvm/Target/TargetLowering.h | 1500 +- include/llvm/Target/TargetLoweringObjectFile.h | 8 + include/llvm/Target/TargetMachine.h | 21 +- include/llvm/Target/TargetOpcodes.h | 19 +- include/llvm/Target/TargetOptions.h | 60 +- include/llvm/Target/TargetRegisterInfo.h | 45 +- include/llvm/Target/TargetSchedule.td | 20 +- include/llvm/Target/TargetSelectionDAG.td | 4 + include/llvm/Target/TargetSelectionDAGInfo.h | 74 +- include/llvm/Target/TargetSubtargetInfo.h | 18 + include/llvm/Transforms/IPO.h | 10 +- include/llvm/Transforms/IPO/PassManagerBuilder.h | 17 +- include/llvm/Transforms/Instrumentation.h | 67 +- include/llvm/Transforms/Scalar.h | 61 +- include/llvm/Transforms/Utils/BasicBlockUtils.h | 31 +- include/llvm/Transforms/Utils/BlackList.h | 59 - include/llvm/Transforms/Utils/Cloning.h | 3 +- include/llvm/Transforms/Utils/GlobalStatus.h | 82 + include/llvm/Transforms/Utils/Local.h | 43 +- include/llvm/Transforms/Utils/LoopUtils.h | 26 + include/llvm/Transforms/Utils/ModuleUtils.h | 8 + include/llvm/Transforms/Utils/PromoteMemToReg.h | 24 +- include/llvm/Transforms/Utils/SSAUpdater.h | 104 +- include/llvm/Transforms/Utils/SpecialCaseList.h | 110 + .../llvm/Transforms/Utils/UnifyFunctionExitNodes.h | 2 +- include/llvm/Transforms/Utils/ValueMapper.h | 31 +- include/llvm/Transforms/Vectorize.h | 2 +- lib/Analysis/AliasAnalysis.cpp | 47 +- lib/Analysis/AliasSetTracker.cpp | 2 - lib/Analysis/Analysis.cpp | 11 +- lib/Analysis/BasicAliasAnalysis.cpp | 122 +- lib/Analysis/BlockFrequencyInfo.cpp | 118 +- lib/Analysis/BranchProbabilityInfo.cpp | 115 +- lib/Analysis/CFG.cpp | 245 + lib/Analysis/CMakeLists.txt | 12 +- lib/Analysis/CaptureTracking.cpp | 14 +- lib/Analysis/ConstantFolding.cpp | 228 +- lib/Analysis/CostModel.cpp | 289 +- lib/Analysis/Delinearization.cpp | 133 + lib/Analysis/DependenceAnalysis.cpp | 85 +- lib/Analysis/IPA/CallGraph.cpp | 230 +- lib/Analysis/IPA/CallGraphSCCPass.cpp | 2 +- lib/Analysis/IPA/GlobalsModRef.cpp | 2 +- lib/Analysis/IPA/IPA.cpp | 3 +- lib/Analysis/IPA/InlineCost.cpp | 159 +- lib/Analysis/InstructionSimplify.cpp | 46 +- lib/Analysis/LazyValueInfo.cpp | 8 +- lib/Analysis/Lint.cpp | 42 +- lib/Analysis/LoopInfo.cpp | 97 +- lib/Analysis/LoopPass.cpp | 4 + lib/Analysis/MemoryBuiltins.cpp | 114 +- lib/Analysis/MemoryDependenceAnalysis.cpp | 15 +- lib/Analysis/PathNumbering.cpp | 521 - lib/Analysis/PathProfileInfo.cpp | 433 - lib/Analysis/PathProfileVerifier.cpp | 206 - lib/Analysis/ProfileDataLoader.cpp | 155 - lib/Analysis/ProfileDataLoaderPass.cpp | 188 - lib/Analysis/ProfileEstimatorPass.cpp | 426 - lib/Analysis/ProfileInfo.cpp | 1079 - lib/Analysis/ProfileInfoLoader.cpp | 155 - lib/Analysis/ProfileInfoLoaderPass.cpp | 267 - lib/Analysis/ProfileVerifierPass.cpp | 383 - lib/Analysis/RegionInfo.cpp | 6 +- lib/Analysis/ScalarEvolution.cpp | 1112 +- lib/Analysis/ScalarEvolutionExpander.cpp | 145 +- lib/Analysis/ScalarEvolutionNormalization.cpp | 18 +- lib/Analysis/TargetTransformInfo.cpp | 76 +- lib/Analysis/TypeBasedAliasAnalysis.cpp | 116 +- lib/Analysis/ValueTracking.cpp | 88 +- lib/Archive/Archive.cpp | 262 - lib/Archive/ArchiveInternals.h | 88 - lib/Archive/ArchiveReader.cpp | 633 - lib/Archive/ArchiveWriter.cpp | 489 - lib/Archive/CMakeLists.txt | 5 - lib/Archive/LLVMBuild.txt | 22 - lib/Archive/Makefile | 17 - lib/AsmParser/LLLexer.cpp | 11 +- lib/AsmParser/LLParser.cpp | 91 +- lib/AsmParser/LLParser.h | 4 +- lib/AsmParser/LLToken.h | 12 +- lib/AsmParser/Parser.cpp | 2 +- lib/Bitcode/Reader/BitcodeReader.cpp | 928 +- lib/Bitcode/Reader/BitcodeReader.h | 104 +- lib/Bitcode/Reader/BitstreamReader.cpp | 13 +- lib/Bitcode/Writer/BitWriter.cpp | 2 +- lib/Bitcode/Writer/BitcodeWriter.cpp | 226 +- lib/Bitcode/Writer/ValueEnumerator.cpp | 5 + lib/Bitcode/Writer/ValueEnumerator.h | 2 +- lib/CMakeLists.txt | 2 +- lib/CodeGen/AggressiveAntiDepBreaker.cpp | 6 +- lib/CodeGen/Analysis.cpp | 475 +- lib/CodeGen/AsmPrinter/ARMException.cpp | 18 +- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 418 +- lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 49 +- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 4 +- lib/CodeGen/AsmPrinter/CMakeLists.txt | 3 + lib/CodeGen/AsmPrinter/DIE.cpp | 136 +- lib/CodeGen/AsmPrinter/DIE.h | 174 +- lib/CodeGen/AsmPrinter/DIEHash.cpp | 507 + lib/CodeGen/AsmPrinter/DIEHash.h | 147 + lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 87 +- lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 124 +- lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 2 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 1421 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 328 +- lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1611 +- lib/CodeGen/AsmPrinter/DwarfDebug.h | 268 +- lib/CodeGen/AsmPrinter/DwarfException.h | 4 +- lib/CodeGen/BasicTargetTransformInfo.cpp | 90 +- lib/CodeGen/BranchFolding.cpp | 19 +- lib/CodeGen/BranchFolding.h | 6 +- lib/CodeGen/CMakeLists.txt | 4 +- lib/CodeGen/CalcSpillWeights.cpp | 41 +- lib/CodeGen/CallingConvLower.cpp | 2 +- lib/CodeGen/CodeGen.cpp | 2 - lib/CodeGen/CriticalAntiDepBreaker.cpp | 8 +- lib/CodeGen/CriticalAntiDepBreaker.h | 2 +- lib/CodeGen/DFAPacketizer.cpp | 3 +- lib/CodeGen/DeadMachineInstructionElim.cpp | 4 +- lib/CodeGen/DwarfEHPrepare.cpp | 16 +- lib/CodeGen/ExecutionDepsFix.cpp | 127 +- lib/CodeGen/ExpandPostRAPseudos.cpp | 2 +- lib/CodeGen/IfConversion.cpp | 229 +- lib/CodeGen/InlineSpiller.cpp | 222 +- lib/CodeGen/InterferenceCache.cpp | 8 +- lib/CodeGen/InterferenceCache.h | 2 +- lib/CodeGen/IntrinsicLowering.cpp | 5 +- lib/CodeGen/LLVMTargetMachine.cpp | 50 +- lib/CodeGen/LexicalScopes.cpp | 10 +- lib/CodeGen/LiveDebugVariables.cpp | 92 +- lib/CodeGen/LiveDebugVariables.h | 4 +- lib/CodeGen/LiveInterval.cpp | 401 +- lib/CodeGen/LiveIntervalAnalysis.cpp | 283 +- lib/CodeGen/LiveRangeCalc.cpp | 56 +- lib/CodeGen/LiveRangeCalc.h | 38 +- lib/CodeGen/LiveRangeEdit.cpp | 246 +- lib/CodeGen/LiveRegMatrix.cpp | 6 +- lib/CodeGen/LiveRegUnits.cpp | 111 + lib/CodeGen/LiveVariables.cpp | 37 +- lib/CodeGen/MachineBasicBlock.cpp | 41 +- lib/CodeGen/MachineBlockFrequencyInfo.cpp | 5 - lib/CodeGen/MachineBlockPlacement.cpp | 26 +- lib/CodeGen/MachineCSE.cpp | 8 +- lib/CodeGen/MachineCopyPropagation.cpp | 5 +- lib/CodeGen/MachineFunction.cpp | 57 +- lib/CodeGen/MachineInstr.cpp | 65 +- lib/CodeGen/MachineLICM.cpp | 20 +- lib/CodeGen/MachineModuleInfo.cpp | 7 +- lib/CodeGen/MachineRegisterInfo.cpp | 56 +- lib/CodeGen/MachineSSAUpdater.cpp | 2 +- lib/CodeGen/MachineScheduler.cpp | 1456 +- lib/CodeGen/MachineSink.cpp | 38 +- lib/CodeGen/MachineTraceMetrics.cpp | 10 +- lib/CodeGen/MachineVerifier.cpp | 418 +- lib/CodeGen/PHIElimination.cpp | 30 +- lib/CodeGen/PHIEliminationUtils.h | 2 +- lib/CodeGen/Passes.cpp | 31 +- lib/CodeGen/PeepholeOptimizer.cpp | 250 +- lib/CodeGen/PostRASchedulerList.cpp | 47 +- lib/CodeGen/ProcessImplicitDefs.cpp | 2 +- lib/CodeGen/PrologEpilogInserter.cpp | 434 +- lib/CodeGen/PrologEpilogInserter.h | 103 +- lib/CodeGen/README.txt | 2 +- lib/CodeGen/RegAllocBase.cpp | 16 +- lib/CodeGen/RegAllocBase.h | 7 +- lib/CodeGen/RegAllocBasic.cpp | 18 +- lib/CodeGen/RegAllocFast.cpp | 60 +- lib/CodeGen/RegAllocGreedy.cpp | 199 +- lib/CodeGen/RegAllocPBQP.cpp | 64 +- lib/CodeGen/RegisterClassInfo.cpp | 32 + lib/CodeGen/RegisterCoalescer.cpp | 249 +- lib/CodeGen/RegisterPressure.cpp | 496 +- lib/CodeGen/RegisterScavenging.cpp | 19 +- lib/CodeGen/ScheduleDAG.cpp | 10 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 139 +- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2537 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 98 +- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 46 +- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 48 +- lib/CodeGen/SelectionDAG/InstrEmitter.h | 2 +- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 581 +- lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 225 +- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 399 +- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 85 +- lib/CodeGen/SelectionDAG/LegalizeTypes.h | 39 +- lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 123 +- lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp | 78 +- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 532 +- lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp | 21 +- lib/CodeGen/SelectionDAG/SDNodeOrdering.h | 56 - lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 12 +- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 33 +- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 39 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 859 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 1825 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 272 +- lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 19 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 362 +- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 156 +- lib/CodeGen/ShrinkWrapping.cpp | 1152 - lib/CodeGen/SjLjEHPrepare.cpp | 218 +- lib/CodeGen/SpillPlacement.cpp | 159 +- lib/CodeGen/SpillPlacement.h | 7 +- lib/CodeGen/Spiller.cpp | 33 +- lib/CodeGen/SplitKit.cpp | 63 +- lib/CodeGen/SplitKit.h | 4 +- lib/CodeGen/StackColoring.cpp | 40 +- lib/CodeGen/StackMaps.cpp | 314 + lib/CodeGen/StackProtector.cpp | 485 +- lib/CodeGen/StackSlotColoring.cpp | 100 +- lib/CodeGen/StrongPHIElimination.cpp | 825 - lib/CodeGen/TailDuplication.cpp | 38 +- lib/CodeGen/TargetInstrInfo.cpp | 80 +- lib/CodeGen/TargetLoweringBase.cpp | 67 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 48 +- lib/CodeGen/TargetOptionsImpl.cpp | 31 +- lib/CodeGen/TargetRegisterInfo.cpp | 18 +- lib/CodeGen/TargetSchedule.cpp | 73 +- lib/CodeGen/TwoAddressInstructionPass.cpp | 6 +- lib/CodeGen/UnreachableBlockElim.cpp | 4 - lib/CodeGen/VirtRegMap.cpp | 46 +- lib/DebugInfo/CMakeLists.txt | 3 + lib/DebugInfo/DWARFAbbreviationDeclaration.cpp | 76 +- lib/DebugInfo/DWARFAbbreviationDeclaration.h | 29 +- lib/DebugInfo/DWARFAttribute.h | 30 - lib/DebugInfo/DWARFCompileUnit.cpp | 258 +- lib/DebugInfo/DWARFCompileUnit.h | 125 +- lib/DebugInfo/DWARFContext.cpp | 327 +- lib/DebugInfo/DWARFContext.h | 93 +- lib/DebugInfo/DWARFDebugArangeSet.cpp | 49 - lib/DebugInfo/DWARFDebugArangeSet.h | 5 - lib/DebugInfo/DWARFDebugAranges.cpp | 206 +- lib/DebugInfo/DWARFDebugAranges.h | 92 +- lib/DebugInfo/DWARFDebugInfoEntry.cpp | 311 +- lib/DebugInfo/DWARFDebugInfoEntry.h | 90 +- lib/DebugInfo/DWARFDebugLine.cpp | 2 +- lib/DebugInfo/DWARFDebugLoc.cpp | 74 + lib/DebugInfo/DWARFDebugLoc.h | 60 + lib/DebugInfo/DWARFFormValue.cpp | 310 +- lib/DebugInfo/DWARFTypeUnit.cpp | 39 + lib/DebugInfo/DWARFTypeUnit.h | 35 + lib/DebugInfo/DWARFUnit.cpp | 365 + lib/DebugInfo/DWARFUnit.h | 168 + lib/DebugInfo/LLVMBuild.txt | 2 +- lib/ExecutionEngine/CMakeLists.txt | 1 + lib/ExecutionEngine/ExecutionEngine.cpp | 63 +- lib/ExecutionEngine/ExecutionEngineBindings.cpp | 111 +- .../IntelJITEvents/IntelJITEventsWrapper.h | 2 +- lib/ExecutionEngine/Interpreter/Execution.cpp | 746 +- .../Interpreter/ExternalFunctions.cpp | 31 +- lib/ExecutionEngine/Interpreter/Interpreter.h | 6 + lib/ExecutionEngine/JIT/CMakeLists.txt | 1 - lib/ExecutionEngine/JIT/JIT.cpp | 156 - lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp | 596 - lib/ExecutionEngine/JIT/JITDwarfEmitter.h | 77 - lib/ExecutionEngine/JIT/JITEmitter.cpp | 52 +- lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 44 +- lib/ExecutionEngine/MCJIT/MCJIT.cpp | 296 +- lib/ExecutionEngine/MCJIT/MCJIT.h | 244 +- lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp | 112 +- .../OProfileJIT/OProfileJITEventListener.cpp | 66 + .../OProfileJIT/OProfileWrapper.cpp | 17 +- lib/ExecutionEngine/RTDyldMemoryManager.cpp | 282 + lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h | 1 + .../RuntimeDyld/ObjectImageCommon.h | 1 + lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 220 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 462 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 55 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 104 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 172 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 32 +- lib/ExecutionEngine/TargetSelect.cpp | 8 + lib/IR/AsmWriter.cpp | 139 +- lib/IR/AsmWriter.h | 118 + lib/IR/AttributeImpl.h | 220 +- lib/IR/Attributes.cpp | 153 +- lib/IR/AutoUpgrade.cpp | 118 +- lib/IR/CMakeLists.txt | 3 +- lib/IR/ConstantFold.cpp | 93 +- lib/IR/Constants.cpp | 66 +- lib/IR/Core.cpp | 118 +- lib/IR/DIBuilder.cpp | 589 +- lib/IR/DataLayout.cpp | 26 +- lib/IR/DebugInfo.cpp | 803 +- lib/IR/Function.cpp | 56 +- lib/IR/GCOV.cpp | 297 +- lib/IR/Globals.cpp | 16 +- lib/IR/Instruction.cpp | 25 +- lib/IR/Instructions.cpp | 369 +- lib/IR/LLVMContextImpl.h | 5 + lib/IR/LegacyPassManager.cpp | 1920 ++ lib/IR/Metadata.cpp | 8 +- lib/IR/Module.cpp | 75 +- lib/IR/PassManager.cpp | 1985 +- lib/IR/PassRegistry.cpp | 21 +- lib/IR/Type.cpp | 6 +- lib/IR/TypeFinder.cpp | 31 +- lib/IR/Value.cpp | 74 +- lib/IR/ValueTypes.cpp | 10 + lib/IR/Verifier.cpp | 439 +- lib/IRReader/IRReader.cpp | 40 +- lib/LLVMBuild.txt | 2 +- lib/LTO/CMakeLists.txt | 4 + lib/LTO/LLVMBuild.txt | 22 + lib/LTO/LTOCodeGenerator.cpp | 521 + lib/LTO/LTOModule.cpp | 794 + lib/LTO/Makefile | 15 + lib/Linker/LinkModules.cpp | 168 +- lib/MC/CMakeLists.txt | 8 + lib/MC/ELFObjectWriter.cpp | 76 +- lib/MC/MCAsmBackend.cpp | 4 +- lib/MC/MCAsmInfo.cpp | 15 +- lib/MC/MCAsmInfoCOFF.cpp | 1 - lib/MC/MCAsmInfoDarwin.cpp | 2 - lib/MC/MCAsmInfoELF.cpp | 23 + lib/MC/MCAsmStreamer.cpp | 310 +- lib/MC/MCAssembler.cpp | 17 +- lib/MC/MCAtom.cpp | 123 +- lib/MC/MCContext.cpp | 84 +- lib/MC/MCDisassembler.cpp | 42 + lib/MC/MCDisassembler/Disassembler.cpp | 171 +- lib/MC/MCDisassembler/Disassembler.h | 9 + lib/MC/MCDwarf.cpp | 201 +- lib/MC/MCELF.cpp | 7 +- lib/MC/MCELFObjectTargetWriter.cpp | 18 +- lib/MC/MCELFStreamer.cpp | 122 +- lib/MC/MCExpr.cpp | 205 +- lib/MC/MCExternalSymbolizer.cpp | 181 + lib/MC/MCFunction.cpp | 81 + lib/MC/MCInstPrinter.cpp | 65 +- lib/MC/MCInstrAnalysis.cpp | 9 +- lib/MC/MCMachOStreamer.cpp | 36 +- lib/MC/MCModule.cpp | 125 +- lib/MC/MCModuleYAML.cpp | 461 + lib/MC/MCNullStreamer.cpp | 20 +- lib/MC/MCObjectDisassembler.cpp | 584 + lib/MC/MCObjectFileInfo.cpp | 41 +- lib/MC/MCObjectStreamer.cpp | 48 +- lib/MC/MCObjectSymbolizer.cpp | 310 + lib/MC/MCParser/AsmLexer.cpp | 58 +- lib/MC/MCParser/AsmParser.cpp | 1658 +- lib/MC/MCParser/COFFAsmParser.cpp | 284 +- lib/MC/MCParser/DarwinAsmParser.cpp | 43 +- lib/MC/MCParser/ELFAsmParser.cpp | 121 +- lib/MC/MCPureStreamer.cpp | 20 +- lib/MC/MCRegisterInfo.cpp | 12 + lib/MC/MCRelocationInfo.cpp | 39 + lib/MC/MCSectionCOFF.cpp | 24 +- lib/MC/MCSectionELF.cpp | 57 +- lib/MC/MCStreamer.cpp | 149 +- lib/MC/MCSubtargetInfo.cpp | 9 +- lib/MC/MCSymbol.cpp | 17 +- lib/MC/MCSymbolizer.cpp | 20 + lib/MC/MCWin64EH.cpp | 50 +- lib/MC/MachObjectWriter.cpp | 117 +- lib/MC/SubtargetFeature.cpp | 8 +- lib/MC/WinCOFFObjectWriter.cpp | 106 +- lib/MC/WinCOFFStreamer.cpp | 27 +- lib/Makefile | 7 +- lib/Object/Archive.cpp | 279 +- lib/Object/Binary.cpp | 57 +- lib/Object/CMakeLists.txt | 5 + lib/Object/COFFObjectFile.cpp | 438 +- lib/Object/COFFYAML.cpp | 281 + lib/Object/ELF.cpp | 714 + lib/Object/ELFObjectFile.cpp | 5 +- lib/Object/ELFYAML.cpp | 338 + lib/Object/Error.cpp | 10 +- lib/Object/MachOObjectFile.cpp | 897 +- lib/Object/MachOUniversal.cpp | 139 + lib/Object/Object.cpp | 5 +- lib/Object/ObjectFile.cpp | 66 +- lib/Object/YAML.cpp | 68 + lib/Option/ArgList.cpp | 15 + lib/Option/CMakeLists.txt | 2 - lib/Option/OptTable.cpp | 111 +- lib/Option/Option.cpp | 53 +- lib/Support/APFloat.cpp | 696 +- lib/Support/APInt.cpp | 62 +- lib/Support/Allocator.cpp | 7 +- lib/Support/BlockFrequency.cpp | 150 +- lib/Support/CMakeLists.txt | 6 +- lib/Support/CommandLine.cpp | 352 +- lib/Support/Compression.cpp | 7 + lib/Support/ConstantRange.cpp | 21 +- lib/Support/ConvertUTFWrapper.cpp | 55 + lib/Support/CrashRecoveryContext.cpp | 44 +- lib/Support/DataStream.cpp | 15 +- lib/Support/Disassembler.cpp | 10 +- lib/Support/Dwarf.cpp | 62 +- lib/Support/DynamicLibrary.cpp | 41 +- lib/Support/Errno.cpp | 33 +- lib/Support/ErrorHandling.cpp | 22 + lib/Support/FileOutputBuffer.cpp | 29 +- lib/Support/FileUtilities.cpp | 33 +- lib/Support/FormattedStream.cpp | 45 +- lib/Support/GraphWriter.cpp | 71 +- lib/Support/Host.cpp | 217 +- lib/Support/Locale.cpp | 33 +- lib/Support/LocaleGeneric.inc | 17 - lib/Support/LocaleWindows.inc | 15 - lib/Support/LocaleXlocale.inc | 61 - lib/Support/LockFileManager.cpp | 31 +- lib/Support/MD5.cpp | 286 + lib/Support/MemoryBuffer.cpp | 132 +- lib/Support/MemoryObject.cpp | 6 +- lib/Support/Path.cpp | 1132 +- lib/Support/PathV2.cpp | 949 - lib/Support/PrettyStackTrace.cpp | 58 +- lib/Support/Process.cpp | 18 + lib/Support/Program.cpp | 51 +- lib/Support/Regex.cpp | 9 +- lib/Support/SmallPtrSet.cpp | 9 +- lib/Support/SourceMgr.cpp | 21 +- lib/Support/StreamableMemoryObject.cpp | 11 +- lib/Support/StringRef.cpp | 31 +- lib/Support/StringRefMemoryObject.cpp | 29 + lib/Support/SystemUtils.cpp | 22 - lib/Support/TargetRegistry.cpp | 6 +- lib/Support/ThreadLocal.cpp | 2 +- lib/Support/Timer.cpp | 4 +- lib/Support/ToolOutputFile.cpp | 20 +- lib/Support/Triple.cpp | 27 +- lib/Support/Unicode.cpp | 367 + lib/Support/Unix/Memory.inc | 7 + lib/Support/Unix/Path.inc | 1197 +- lib/Support/Unix/PathV2.inc | 693 - lib/Support/Unix/Process.inc | 119 +- lib/Support/Unix/Program.inc | 217 +- lib/Support/Unix/Signals.inc | 18 +- lib/Support/Unix/ThreadLocal.inc | 2 +- lib/Support/Unix/TimeValue.inc | 19 +- lib/Support/Unix/Unix.h | 14 +- lib/Support/Windows/DynamicLibrary.inc | 15 +- lib/Support/Windows/Memory.inc | 4 +- lib/Support/Windows/Path.inc | 1712 +- lib/Support/Windows/PathV2.inc | 1022 - lib/Support/Windows/Process.inc | 116 +- lib/Support/Windows/Program.inc | 288 +- lib/Support/Windows/RWMutex.inc | 4 +- lib/Support/Windows/Signals.inc | 56 +- lib/Support/Windows/TimeValue.inc | 38 +- lib/Support/Windows/Windows.h | 30 +- lib/Support/YAMLParser.cpp | 111 +- lib/Support/YAMLTraits.cpp | 100 +- lib/Support/raw_ostream.cpp | 48 +- lib/TableGen/Main.cpp | 2 +- lib/TableGen/Record.cpp | 31 +- lib/TableGen/TGParser.cpp | 12 +- lib/Target/AArch64/AArch64.td | 7 +- lib/Target/AArch64/AArch64AsmPrinter.cpp | 172 +- lib/Target/AArch64/AArch64AsmPrinter.h | 4 - lib/Target/AArch64/AArch64BranchFixupPass.cpp | 2 +- lib/Target/AArch64/AArch64CallingConv.td | 9 +- lib/Target/AArch64/AArch64FrameLowering.cpp | 35 +- lib/Target/AArch64/AArch64FrameLowering.h | 2 +- lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 1066 +- lib/Target/AArch64/AArch64ISelLowering.cpp | 1814 +- lib/Target/AArch64/AArch64ISelLowering.h | 147 +- lib/Target/AArch64/AArch64InstrFormats.td | 528 + lib/Target/AArch64/AArch64InstrInfo.cpp | 105 +- lib/Target/AArch64/AArch64InstrInfo.h | 4 - lib/Target/AArch64/AArch64InstrInfo.td | 87 +- lib/Target/AArch64/AArch64InstrNEON.td | 8671 +++++++ lib/Target/AArch64/AArch64MCInstLower.cpp | 7 +- lib/Target/AArch64/AArch64RegisterInfo.cpp | 7 +- lib/Target/AArch64/AArch64RegisterInfo.h | 7 +- lib/Target/AArch64/AArch64RegisterInfo.td | 176 +- lib/Target/AArch64/AArch64Subtarget.cpp | 28 +- lib/Target/AArch64/AArch64Subtarget.h | 20 +- lib/Target/AArch64/AArch64TargetMachine.cpp | 1 + lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 521 +- lib/Target/AArch64/CMakeLists.txt | 2 + .../AArch64/Disassembler/AArch64Disassembler.cpp | 795 +- .../AArch64/InstPrinter/AArch64InstPrinter.cpp | 131 + .../AArch64/InstPrinter/AArch64InstPrinter.h | 14 +- .../AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 4 +- .../AArch64/MCTargetDesc/AArch64ELFStreamer.cpp | 20 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 5 +- lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h | 10 +- .../AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp | 106 +- .../AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp | 21 +- .../AArch64/MCTargetDesc/AArch64MCTargetDesc.h | 5 +- .../AArch64/TargetInfo/AArch64TargetInfo.cpp | 2 +- lib/Target/AArch64/Utils/AArch64BaseInfo.cpp | 68 +- lib/Target/AArch64/Utils/AArch64BaseInfo.h | 65 +- lib/Target/AArch64/Utils/CMakeLists.txt | 2 + lib/Target/ARM/A15SDOptimizer.cpp | 13 +- lib/Target/ARM/ARM.td | 94 +- lib/Target/ARM/ARMAsmPrinter.cpp | 605 +- lib/Target/ARM/ARMAsmPrinter.h | 8 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 470 +- lib/Target/ARM/ARMBaseInstrInfo.h | 28 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 99 +- lib/Target/ARM/ARMBaseRegisterInfo.h | 27 +- lib/Target/ARM/ARMBuildAttrs.h | 71 +- lib/Target/ARM/ARMCallingConv.td | 26 +- lib/Target/ARM/ARMCodeEmitter.cpp | 6 +- lib/Target/ARM/ARMConstantIslandPass.cpp | 3 +- lib/Target/ARM/ARMConstantPoolValue.cpp | 50 +- lib/Target/ARM/ARMConstantPoolValue.h | 33 + lib/Target/ARM/ARMExpandPseudoInsts.cpp | 75 +- lib/Target/ARM/ARMFPUName.def | 32 + lib/Target/ARM/ARMFPUName.h | 26 + lib/Target/ARM/ARMFastISel.cpp | 375 +- lib/Target/ARM/ARMFeatures.h | 93 + lib/Target/ARM/ARMFrameLowering.cpp | 156 +- lib/Target/ARM/ARMHazardRecognizer.cpp | 10 +- lib/Target/ARM/ARMHazardRecognizer.h | 13 +- lib/Target/ARM/ARMISelDAGToDAG.cpp | 566 +- lib/Target/ARM/ARMISelLowering.cpp | 1722 +- lib/Target/ARM/ARMISelLowering.h | 72 +- lib/Target/ARM/ARMInstrFormats.td | 290 +- lib/Target/ARM/ARMInstrInfo.cpp | 34 +- lib/Target/ARM/ARMInstrInfo.td | 885 +- lib/Target/ARM/ARMInstrNEON.td | 451 +- lib/Target/ARM/ARMInstrThumb.td | 263 +- lib/Target/ARM/ARMInstrThumb2.td | 849 +- lib/Target/ARM/ARMInstrVFP.td | 348 +- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 115 +- lib/Target/ARM/ARMMCInstLower.cpp | 2 +- lib/Target/ARM/ARMMachineFunctionInfo.h | 78 +- lib/Target/ARM/ARMRegisterInfo.cpp | 5 +- lib/Target/ARM/ARMRegisterInfo.h | 6 +- lib/Target/ARM/ARMRegisterInfo.td | 84 +- lib/Target/ARM/ARMSchedule.td | 18 + lib/Target/ARM/ARMScheduleA9.td | 196 +- lib/Target/ARM/ARMScheduleSwift.td | 944 +- lib/Target/ARM/ARMSelectionDAGInfo.cpp | 4 +- lib/Target/ARM/ARMSelectionDAGInfo.h | 4 +- lib/Target/ARM/ARMSubtarget.cpp | 120 +- lib/Target/ARM/ARMSubtarget.h | 79 +- lib/Target/ARM/ARMTargetMachine.cpp | 15 +- lib/Target/ARM/ARMTargetObjectFile.cpp | 2 +- lib/Target/ARM/ARMTargetTransformInfo.cpp | 113 +- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1429 +- lib/Target/ARM/CMakeLists.txt | 2 +- lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 817 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 284 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 4 + lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h | 12 +- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 53 +- lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 61 +- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 735 +- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.h | 27 - lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 2 - lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h | 3 +- lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 102 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 93 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 16 +- .../ARM/MCTargetDesc/ARMMachORelocationInfo.cpp | 43 + .../ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 129 +- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp | 157 +- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h | 73 +- lib/Target/ARM/MCTargetDesc/CMakeLists.txt | 1 + lib/Target/ARM/Thumb1FrameLowering.cpp | 36 +- lib/Target/ARM/Thumb1InstrInfo.cpp | 2 +- lib/Target/ARM/Thumb1RegisterInfo.cpp | 20 +- lib/Target/ARM/Thumb1RegisterInfo.h | 2 +- lib/Target/ARM/Thumb2ITBlockPass.cpp | 71 +- lib/Target/ARM/Thumb2InstrInfo.cpp | 25 +- lib/Target/ARM/Thumb2RegisterInfo.cpp | 6 +- lib/Target/ARM/Thumb2RegisterInfo.h | 6 +- lib/Target/CppBackend/CPPBackend.cpp | 27 +- lib/Target/Hexagon/CMakeLists.txt | 7 +- lib/Target/Hexagon/Hexagon.h | 6 +- lib/Target/Hexagon/Hexagon.td | 30 +- lib/Target/Hexagon/HexagonAsmPrinter.cpp | 4 +- lib/Target/Hexagon/HexagonCallingConvLower.cpp | 8 +- lib/Target/Hexagon/HexagonCallingConvLower.h | 5 +- lib/Target/Hexagon/HexagonCopyToCombine.cpp | 677 + lib/Target/Hexagon/HexagonFrameLowering.cpp | 80 +- lib/Target/Hexagon/HexagonHardwareLoops.cpp | 10 +- lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 76 +- lib/Target/Hexagon/HexagonISelLowering.cpp | 104 +- lib/Target/Hexagon/HexagonISelLowering.h | 17 +- lib/Target/Hexagon/HexagonInstrFormats.td | 5 +- lib/Target/Hexagon/HexagonInstrInfo.cpp | 857 +- lib/Target/Hexagon/HexagonInstrInfo.h | 15 +- lib/Target/Hexagon/HexagonInstrInfo.td | 105 +- lib/Target/Hexagon/HexagonInstrInfoV4.td | 265 +- lib/Target/Hexagon/HexagonInstrInfoV5.td | 23 +- lib/Target/Hexagon/HexagonMCInstLower.cpp | 2 +- lib/Target/Hexagon/HexagonMachineFunctionInfo.cpp | 16 + lib/Target/Hexagon/HexagonMachineFunctionInfo.h | 6 +- lib/Target/Hexagon/HexagonMachineScheduler.cpp | 21 +- lib/Target/Hexagon/HexagonMachineScheduler.h | 5 +- lib/Target/Hexagon/HexagonNewValueJump.cpp | 1 + lib/Target/Hexagon/HexagonPeephole.cpp | 2 +- lib/Target/Hexagon/HexagonRegisterInfo.cpp | 26 +- lib/Target/Hexagon/HexagonRegisterInfo.h | 8 +- lib/Target/Hexagon/HexagonRegisterInfo.td | 4 +- lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp | 2 +- lib/Target/Hexagon/HexagonSelectionDAGInfo.h | 2 +- .../Hexagon/HexagonSplitConst32AndConst64.cpp | 174 + lib/Target/Hexagon/HexagonSubtarget.cpp | 2 + lib/Target/Hexagon/HexagonSubtarget.h | 2 +- lib/Target/Hexagon/HexagonTargetMachine.cpp | 31 +- lib/Target/Hexagon/HexagonTargetObjectFile.cpp | 8 +- lib/Target/Hexagon/HexagonTargetObjectFile.h | 1 + lib/Target/Hexagon/HexagonVLIWPacketizer.cpp | 1833 +- .../Hexagon/InstPrinter/HexagonInstPrinter.cpp | 15 +- lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h | 5 +- .../Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp | 6 +- lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h | 9 +- .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp | 11 +- lib/Target/LLVMBuild.txt | 2 +- lib/Target/MBlaze/AsmParser/CMakeLists.txt | 8 - lib/Target/MBlaze/AsmParser/LLVMBuild.txt | 23 - lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp | 572 - lib/Target/MBlaze/AsmParser/Makefile | 15 - lib/Target/MBlaze/CMakeLists.txt | 37 - lib/Target/MBlaze/Disassembler/CMakeLists.txt | 16 - lib/Target/MBlaze/Disassembler/LLVMBuild.txt | 23 - .../MBlaze/Disassembler/MBlazeDisassembler.cpp | 719 - .../MBlaze/Disassembler/MBlazeDisassembler.h | 49 - lib/Target/MBlaze/Disassembler/Makefile | 16 - lib/Target/MBlaze/InstPrinter/CMakeLists.txt | 8 - lib/Target/MBlaze/InstPrinter/LLVMBuild.txt | 23 - .../MBlaze/InstPrinter/MBlazeInstPrinter.cpp | 71 - lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h | 43 - lib/Target/MBlaze/InstPrinter/Makefile | 16 - lib/Target/MBlaze/LLVMBuild.txt | 34 - lib/Target/MBlaze/MBlaze.h | 32 - lib/Target/MBlaze/MBlaze.td | 73 - lib/Target/MBlaze/MBlazeAsmPrinter.cpp | 326 - lib/Target/MBlaze/MBlazeCallingConv.td | 24 - lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp | 254 - lib/Target/MBlaze/MBlazeFrameLowering.cpp | 488 - lib/Target/MBlaze/MBlazeFrameLowering.h | 56 - lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp | 277 - lib/Target/MBlaze/MBlazeISelLowering.cpp | 1154 - lib/Target/MBlaze/MBlazeISelLowering.h | 179 - lib/Target/MBlaze/MBlazeInstrFPU.td | 219 - lib/Target/MBlaze/MBlazeInstrFSL.td | 229 - lib/Target/MBlaze/MBlazeInstrFormats.td | 228 - lib/Target/MBlaze/MBlazeInstrInfo.cpp | 297 - lib/Target/MBlaze/MBlazeInstrInfo.h | 240 - lib/Target/MBlaze/MBlazeInstrInfo.td | 1051 - lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp | 112 - lib/Target/MBlaze/MBlazeIntrinsicInfo.h | 33 - lib/Target/MBlaze/MBlazeIntrinsics.td | 131 - lib/Target/MBlaze/MBlazeMCInstLower.cpp | 167 - lib/Target/MBlaze/MBlazeMCInstLower.h | 47 - lib/Target/MBlaze/MBlazeMachineFunction.cpp | 14 - lib/Target/MBlaze/MBlazeMachineFunction.h | 169 - lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 145 - lib/Target/MBlaze/MBlazeRegisterInfo.h | 71 - lib/Target/MBlaze/MBlazeRegisterInfo.td | 148 - lib/Target/MBlaze/MBlazeRelocations.h | 47 - lib/Target/MBlaze/MBlazeSchedule.td | 50 - lib/Target/MBlaze/MBlazeSchedule3.td | 236 - lib/Target/MBlaze/MBlazeSchedule5.td | 267 - lib/Target/MBlaze/MBlazeSelectionDAGInfo.cpp | 23 - lib/Target/MBlaze/MBlazeSelectionDAGInfo.h | 31 - lib/Target/MBlaze/MBlazeSubtarget.cpp | 56 - lib/Target/MBlaze/MBlazeSubtarget.h | 75 - lib/Target/MBlaze/MBlazeTargetMachine.cpp | 81 - lib/Target/MBlaze/MBlazeTargetMachine.h | 80 - lib/Target/MBlaze/MBlazeTargetObjectFile.cpp | 90 - lib/Target/MBlaze/MBlazeTargetObjectFile.h | 40 - lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt | 9 - lib/Target/MBlaze/MCTargetDesc/LLVMBuild.txt | 23 - .../MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp | 171 - lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h | 237 - .../MBlaze/MCTargetDesc/MBlazeELFObjectWriter.cpp | 77 - lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp | 26 - lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h | 30 - .../MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp | 222 - .../MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp | 141 - .../MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h | 56 - lib/Target/MBlaze/MCTargetDesc/Makefile | 16 - lib/Target/MBlaze/Makefile | 23 - lib/Target/MBlaze/TODO | 21 - lib/Target/MBlaze/TargetInfo/CMakeLists.txt | 8 - lib/Target/MBlaze/TargetInfo/LLVMBuild.txt | 23 - lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp | 19 - lib/Target/MBlaze/TargetInfo/Makefile | 15 - lib/Target/MSP430/CMakeLists.txt | 2 +- lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp | 5 +- lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h | 7 +- lib/Target/MSP430/MSP430AsmPrinter.cpp | 2 +- lib/Target/MSP430/MSP430CallingConv.td | 7 +- lib/Target/MSP430/MSP430FrameLowering.h | 4 +- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 10 +- lib/Target/MSP430/MSP430ISelLowering.cpp | 191 +- lib/Target/MSP430/MSP430ISelLowering.h | 13 +- lib/Target/MSP430/MSP430InstrInfo.cpp | 7 +- lib/Target/MSP430/MSP430InstrInfo.h | 1 + lib/Target/MSP430/MSP430InstrInfo.td | 4 +- lib/Target/MSP430/MSP430MCInstLower.cpp | 2 +- lib/Target/MSP430/MSP430RegisterInfo.cpp | 6 +- lib/Target/MSP430/MSP430RegisterInfo.h | 3 +- lib/Target/MSP430/MSP430RegisterInfo.td | 2 +- lib/Target/MSP430/MSP430TargetMachine.cpp | 4 +- lib/Target/Mangler.cpp | 149 +- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 1572 +- lib/Target/Mips/CMakeLists.txt | 4 +- lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 446 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp | 89 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.h | 9 +- lib/Target/Mips/MCTargetDesc/CMakeLists.txt | 3 +- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 43 +- .../Mips/MCTargetDesc/MipsDirectObjLower.cpp | 81 - lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.h | 28 - .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 39 + lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp | 89 - lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h | 43 - lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h | 39 + lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 3 +- lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h | 7 +- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 210 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 49 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h | 16 +- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 67 + lib/Target/Mips/MSA.txt | 78 + lib/Target/Mips/MicroMipsInstrFormats.td | 196 +- lib/Target/Mips/MicroMipsInstrInfo.td | 228 +- lib/Target/Mips/Mips.h | 1 - lib/Target/Mips/Mips.td | 3 + lib/Target/Mips/Mips16FrameLowering.cpp | 26 +- lib/Target/Mips/Mips16FrameLowering.h | 2 +- lib/Target/Mips/Mips16HardFloat.cpp | 517 + lib/Target/Mips/Mips16HardFloat.h | 54 + lib/Target/Mips/Mips16ISelDAGToDAG.cpp | 21 +- lib/Target/Mips/Mips16ISelDAGToDAG.h | 2 +- lib/Target/Mips/Mips16ISelLowering.cpp | 239 +- lib/Target/Mips/Mips16ISelLowering.h | 4 +- lib/Target/Mips/Mips16InstrFormats.td | 18 +- lib/Target/Mips/Mips16InstrInfo.cpp | 203 +- lib/Target/Mips/Mips16InstrInfo.h | 15 +- lib/Target/Mips/Mips16InstrInfo.td | 188 +- lib/Target/Mips/Mips16RegisterInfo.cpp | 17 +- lib/Target/Mips/Mips16RegisterInfo.h | 4 +- lib/Target/Mips/Mips64InstrInfo.td | 440 +- lib/Target/Mips/MipsAnalyzeImmediate.cpp | 2 +- lib/Target/Mips/MipsAnalyzeImmediate.h | 10 +- lib/Target/Mips/MipsAsmPrinter.cpp | 141 +- lib/Target/Mips/MipsAsmPrinter.h | 25 +- lib/Target/Mips/MipsCallingConv.td | 30 +- lib/Target/Mips/MipsCodeEmitter.cpp | 40 +- lib/Target/Mips/MipsCondMov.td | 210 +- lib/Target/Mips/MipsConstantIslandPass.cpp | 1470 +- lib/Target/Mips/MipsDSPInstrInfo.td | 468 +- lib/Target/Mips/MipsDelaySlotFiller.cpp | 38 +- lib/Target/Mips/MipsISelDAGToDAG.cpp | 81 +- lib/Target/Mips/MipsISelDAGToDAG.h | 38 + lib/Target/Mips/MipsISelLowering.cpp | 824 +- lib/Target/Mips/MipsISelLowering.h | 184 +- lib/Target/Mips/MipsInstrFPU.td | 456 +- lib/Target/Mips/MipsInstrFormats.td | 143 +- lib/Target/Mips/MipsInstrInfo.cpp | 43 +- lib/Target/Mips/MipsInstrInfo.h | 16 +- lib/Target/Mips/MipsInstrInfo.td | 983 +- lib/Target/Mips/MipsJITInfo.cpp | 6 +- lib/Target/Mips/MipsLongBranch.cpp | 25 +- lib/Target/Mips/MipsMCInstLower.cpp | 5 +- lib/Target/Mips/MipsMCInstLower.h | 4 +- lib/Target/Mips/MipsMSAInstrFormats.td | 406 + lib/Target/Mips/MipsMSAInstrInfo.td | 3694 +++ lib/Target/Mips/MipsMachineFunction.cpp | 72 +- lib/Target/Mips/MipsMachineFunction.h | 103 +- lib/Target/Mips/MipsOs16.cpp | 45 +- lib/Target/Mips/MipsRegisterInfo.cpp | 79 +- lib/Target/Mips/MipsRegisterInfo.h | 8 +- lib/Target/Mips/MipsRegisterInfo.td | 411 +- lib/Target/Mips/MipsSEFrameLowering.cpp | 184 +- lib/Target/Mips/MipsSEFrameLowering.h | 2 +- lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 443 +- lib/Target/Mips/MipsSEISelDAGToDAG.h | 48 +- lib/Target/Mips/MipsSEISelLowering.cpp | 2329 +- lib/Target/Mips/MipsSEISelLowering.h | 48 +- lib/Target/Mips/MipsSEInstrInfo.cpp | 310 +- lib/Target/Mips/MipsSEInstrInfo.h | 40 +- lib/Target/Mips/MipsSERegisterInfo.cpp | 85 +- lib/Target/Mips/MipsSERegisterInfo.h | 5 +- lib/Target/Mips/MipsSchedule.td | 15 +- lib/Target/Mips/MipsSubtarget.cpp | 34 +- lib/Target/Mips/MipsSubtarget.h | 31 +- lib/Target/Mips/MipsTargetMachine.cpp | 21 +- lib/Target/Mips/MipsTargetMachine.h | 6 + lib/Target/Mips/MipsTargetStreamer.h | 44 + lib/Target/NVPTX/CMakeLists.txt | 4 +- lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.cpp | 290 +- lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h | 53 + lib/Target/NVPTX/MCTargetDesc/NVPTXBaseInfo.h | 1 - lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 12 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h | 2 +- .../NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp | 17 + lib/Target/NVPTX/ManagedStringPool.h | 2 +- lib/Target/NVPTX/NVPTX.h | 55 +- lib/Target/NVPTX/NVPTX.td | 6 + lib/Target/NVPTX/NVPTXAllocaHoisting.cpp | 2 +- lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 595 +- lib/Target/NVPTX/NVPTXAsmPrinter.h | 27 +- lib/Target/NVPTX/NVPTXFrameLowering.cpp | 41 +- lib/Target/NVPTX/NVPTXGenericToNVVM.cpp | 4 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 1049 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.h | 31 +- lib/Target/NVPTX/NVPTXISelLowering.cpp | 1627 +- lib/Target/NVPTX/NVPTXISelLowering.h | 39 +- lib/Target/NVPTX/NVPTXInstrInfo.cpp | 51 +- lib/Target/NVPTX/NVPTXInstrInfo.h | 1 + lib/Target/NVPTX/NVPTXInstrInfo.td | 2114 +- lib/Target/NVPTX/NVPTXIntrinsics.td | 632 +- lib/Target/NVPTX/NVPTXMCExpr.cpp | 46 + lib/Target/NVPTX/NVPTXMCExpr.h | 83 + lib/Target/NVPTX/NVPTXNumRegisters.h | 16 - lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp | 225 + lib/Target/NVPTX/NVPTXRegisterInfo.cpp | 13 +- lib/Target/NVPTX/NVPTXRegisterInfo.h | 2 +- lib/Target/NVPTX/NVPTXRegisterInfo.td | 26 +- lib/Target/NVPTX/NVPTXSection.h | 4 +- lib/Target/NVPTX/NVPTXSplitBBatBar.cpp | 2 +- lib/Target/NVPTX/NVPTXSubtarget.cpp | 20 +- lib/Target/NVPTX/NVPTXSubtarget.h | 2 +- lib/Target/NVPTX/NVPTXTargetMachine.cpp | 64 +- lib/Target/NVPTX/NVPTXTargetObjectFile.h | 44 +- lib/Target/NVPTX/NVVMReflect.cpp | 4 +- lib/Target/PowerPC/AsmParser/LLVMBuild.txt | 2 +- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 738 +- lib/Target/PowerPC/CMakeLists.txt | 5 +- lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp | 189 +- lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h | 18 +- lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt | 2 + lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 101 +- .../PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 340 +- lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h | 28 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 9 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h | 3 +- .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 102 +- lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp | 155 + lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h | 96 + .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 84 +- lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 8 +- .../PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp | 389 + lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp | 32 + lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h | 32 +- lib/Target/PowerPC/Makefile | 2 +- lib/Target/PowerPC/PPC.h | 24 +- lib/Target/PowerPC/PPC.td | 66 +- lib/Target/PowerPC/PPCAsmPrinter.cpp | 218 +- lib/Target/PowerPC/PPCCTRLoops.cpp | 1164 +- lib/Target/PowerPC/PPCCallingConv.td | 70 +- lib/Target/PowerPC/PPCCodeEmitter.cpp | 51 +- lib/Target/PowerPC/PPCFastISel.cpp | 2236 ++ lib/Target/PowerPC/PPCFrameLowering.cpp | 635 +- lib/Target/PowerPC/PPCFrameLowering.h | 10 + lib/Target/PowerPC/PPCHazardRecognizers.cpp | 6 +- lib/Target/PowerPC/PPCHazardRecognizers.h | 4 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 115 +- lib/Target/PowerPC/PPCISelLowering.cpp | 1056 +- lib/Target/PowerPC/PPCISelLowering.h | 143 +- lib/Target/PowerPC/PPCInstr64Bit.td | 165 +- lib/Target/PowerPC/PPCInstrAltivec.td | 52 +- lib/Target/PowerPC/PPCInstrFormats.td | 71 +- lib/Target/PowerPC/PPCInstrInfo.cpp | 65 +- lib/Target/PowerPC/PPCInstrInfo.h | 7 +- lib/Target/PowerPC/PPCInstrInfo.td | 805 +- lib/Target/PowerPC/PPCJITInfo.cpp | 40 +- lib/Target/PowerPC/PPCMCInstLower.cpp | 62 +- lib/Target/PowerPC/PPCMachineFunctionInfo.h | 9 +- lib/Target/PowerPC/PPCRegisterInfo.cpp | 264 +- lib/Target/PowerPC/PPCRegisterInfo.h | 11 +- lib/Target/PowerPC/PPCRegisterInfo.td | 20 +- lib/Target/PowerPC/PPCSchedule.td | 8 + lib/Target/PowerPC/PPCScheduleA2.td | 841 +- lib/Target/PowerPC/PPCScheduleE500mc.td | 2 + lib/Target/PowerPC/PPCScheduleE5500.td | 1 + lib/Target/PowerPC/PPCSubtarget.cpp | 154 +- lib/Target/PowerPC/PPCSubtarget.h | 28 +- lib/Target/PowerPC/PPCTargetMachine.cpp | 16 +- lib/Target/PowerPC/PPCTargetObjectFile.cpp | 67 + lib/Target/PowerPC/PPCTargetObjectFile.h | 35 + lib/Target/PowerPC/PPCTargetStreamer.h | 23 + lib/Target/PowerPC/PPCTargetTransformInfo.cpp | 9 + .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 5 +- lib/Target/R600/AMDGPU.h | 66 +- lib/Target/R600/AMDGPU.td | 85 + lib/Target/R600/AMDGPUAsmPrinter.cpp | 86 +- lib/Target/R600/AMDGPUAsmPrinter.h | 12 +- lib/Target/R600/AMDGPUCallingConv.td | 46 +- lib/Target/R600/AMDGPUFrameLowering.cpp | 23 +- lib/Target/R600/AMDGPUISelDAGToDAG.cpp | 585 + lib/Target/R600/AMDGPUISelLowering.cpp | 445 +- lib/Target/R600/AMDGPUISelLowering.h | 56 +- lib/Target/R600/AMDGPUIndirectAddressing.cpp | 343 - lib/Target/R600/AMDGPUInstrInfo.cpp | 140 +- lib/Target/R600/AMDGPUInstrInfo.h | 50 +- lib/Target/R600/AMDGPUInstrInfo.td | 22 +- lib/Target/R600/AMDGPUInstructions.td | 268 +- lib/Target/R600/AMDGPUIntrinsics.td | 2 + lib/Target/R600/AMDGPUMCInstLower.cpp | 43 +- lib/Target/R600/AMDGPUMachineFunction.cpp | 9 +- lib/Target/R600/AMDGPUMachineFunction.h | 9 +- lib/Target/R600/AMDGPURegisterInfo.cpp | 38 +- lib/Target/R600/AMDGPURegisterInfo.h | 11 +- lib/Target/R600/AMDGPURegisterInfo.td | 3 +- lib/Target/R600/AMDGPUStructurizeCFG.cpp | 896 - lib/Target/R600/AMDGPUSubtarget.cpp | 78 +- lib/Target/R600/AMDGPUSubtarget.h | 33 +- lib/Target/R600/AMDGPUTargetMachine.cpp | 81 +- lib/Target/R600/AMDGPUTargetMachine.h | 61 +- lib/Target/R600/AMDGPUTargetTransformInfo.cpp | 90 + lib/Target/R600/AMDIL.h | 121 - lib/Target/R600/AMDIL7XXDevice.cpp | 115 - lib/Target/R600/AMDIL7XXDevice.h | 72 - lib/Target/R600/AMDILBase.td | 64 - lib/Target/R600/AMDILCFGStructurizer.cpp | 4155 ++- lib/Target/R600/AMDILDevice.cpp | 132 - lib/Target/R600/AMDILDevice.h | 117 - lib/Target/R600/AMDILDeviceInfo.cpp | 97 - lib/Target/R600/AMDILDeviceInfo.h | 88 - lib/Target/R600/AMDILDevices.h | 19 - lib/Target/R600/AMDILEvergreenDevice.cpp | 169 - lib/Target/R600/AMDILEvergreenDevice.h | 93 - lib/Target/R600/AMDILISelDAGToDAG.cpp | 666 - lib/Target/R600/AMDILISelLowering.cpp | 61 +- lib/Target/R600/AMDILInstrInfo.td | 67 +- lib/Target/R600/AMDILIntrinsicInfo.cpp | 4 +- lib/Target/R600/AMDILNIDevice.cpp | 65 - lib/Target/R600/AMDILNIDevice.h | 57 - lib/Target/R600/AMDILSIDevice.cpp | 48 - lib/Target/R600/AMDILSIDevice.h | 39 - lib/Target/R600/CMakeLists.txt | 18 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.cpp | 137 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.h | 4 + lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp | 8 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 13 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h | 4 +- .../R600/MCTargetDesc/AMDGPUMCCodeEmitter.cpp | 21 + lib/Target/R600/MCTargetDesc/AMDGPUMCCodeEmitter.h | 1 + .../R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 2 +- lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.h | 4 +- lib/Target/R600/MCTargetDesc/CMakeLists.txt | 1 + lib/Target/R600/MCTargetDesc/R600MCCodeEmitter.cpp | 102 +- lib/Target/R600/Processors.td | 48 +- lib/Target/R600/R600ClauseMergePass.cpp | 204 + lib/Target/R600/R600ControlFlowFinalizer.cpp | 152 +- lib/Target/R600/R600Defines.h | 122 +- lib/Target/R600/R600EmitClauseMarkers.cpp | 164 +- lib/Target/R600/R600ExpandSpecialInstrs.cpp | 90 +- lib/Target/R600/R600ISelLowering.cpp | 1299 +- lib/Target/R600/R600ISelLowering.h | 14 +- lib/Target/R600/R600InstrFormats.td | 492 + lib/Target/R600/R600InstrInfo.cpp | 825 +- lib/Target/R600/R600InstrInfo.h | 121 +- lib/Target/R600/R600Instructions.td | 1785 +- lib/Target/R600/R600Intrinsics.td | 44 + lib/Target/R600/R600MachineFunctionInfo.cpp | 6 +- lib/Target/R600/R600MachineFunctionInfo.h | 3 +- lib/Target/R600/R600MachineScheduler.cpp | 300 +- lib/Target/R600/R600MachineScheduler.h | 44 +- lib/Target/R600/R600OptimizeVectorRegisters.cpp | 380 + lib/Target/R600/R600Packetizer.cpp | 311 +- lib/Target/R600/R600RegisterInfo.cpp | 53 +- lib/Target/R600/R600RegisterInfo.h | 13 +- lib/Target/R600/R600RegisterInfo.td | 79 +- lib/Target/R600/R600Schedule.td | 6 +- lib/Target/R600/R600TextureIntrinsicsReplacer.cpp | 303 + lib/Target/R600/SIAnnotateControlFlow.cpp | 16 +- lib/Target/R600/SIDefines.h | 16 + lib/Target/R600/SIFixSGPRCopies.cpp | 263 + lib/Target/R600/SIISelLowering.cpp | 756 +- lib/Target/R600/SIISelLowering.h | 31 +- lib/Target/R600/SIInsertWaits.cpp | 34 +- lib/Target/R600/SIInstrFormats.td | 116 +- lib/Target/R600/SIInstrInfo.cpp | 524 +- lib/Target/R600/SIInstrInfo.h | 80 +- lib/Target/R600/SIInstrInfo.td | 286 +- lib/Target/R600/SIInstructions.td | 798 +- lib/Target/R600/SIIntrinsics.td | 26 +- lib/Target/R600/SILowerControlFlow.cpp | 38 +- lib/Target/R600/SIMachineFunctionInfo.cpp | 4 + lib/Target/R600/SIMachineFunctionInfo.h | 1 + lib/Target/R600/SIRegisterInfo.cpp | 88 +- lib/Target/R600/SIRegisterInfo.h | 26 +- lib/Target/R600/SIRegisterInfo.td | 18 +- lib/Target/R600/SITypeRewriter.cpp | 162 + lib/Target/R600/TargetInfo/AMDGPUTargetInfo.cpp | 2 +- lib/Target/Sparc/CMakeLists.txt | 6 +- lib/Target/Sparc/DelaySlotFiller.cpp | 267 +- lib/Target/Sparc/FPMover.cpp | 141 - lib/Target/Sparc/LLVMBuild.txt | 4 +- lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h | 22 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 15 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h | 7 +- lib/Target/Sparc/Makefile | 3 +- lib/Target/Sparc/README.txt | 8 +- lib/Target/Sparc/Sparc.h | 24 +- lib/Target/Sparc/Sparc.td | 6 +- lib/Target/Sparc/SparcAsmPrinter.cpp | 112 +- lib/Target/Sparc/SparcCallingConv.td | 13 +- lib/Target/Sparc/SparcCodeEmitter.cpp | 245 + lib/Target/Sparc/SparcFrameLowering.cpp | 228 +- lib/Target/Sparc/SparcFrameLowering.h | 20 +- lib/Target/Sparc/SparcISelDAGToDAG.cpp | 24 +- lib/Target/Sparc/SparcISelLowering.cpp | 1169 +- lib/Target/Sparc/SparcISelLowering.h | 50 +- lib/Target/Sparc/SparcInstr64Bit.td | 103 +- lib/Target/Sparc/SparcInstrFormats.td | 92 +- lib/Target/Sparc/SparcInstrInfo.cpp | 177 +- lib/Target/Sparc/SparcInstrInfo.h | 15 +- lib/Target/Sparc/SparcInstrInfo.td | 528 +- lib/Target/Sparc/SparcJITInfo.cpp | 165 + lib/Target/Sparc/SparcJITInfo.h | 67 + lib/Target/Sparc/SparcMachineFunctionInfo.h | 12 +- lib/Target/Sparc/SparcRegisterInfo.cpp | 166 +- lib/Target/Sparc/SparcRegisterInfo.h | 10 +- lib/Target/Sparc/SparcRegisterInfo.td | 124 +- lib/Target/Sparc/SparcRelocations.h | 41 + lib/Target/Sparc/SparcSubtarget.cpp | 33 +- lib/Target/Sparc/SparcSubtarget.h | 16 +- lib/Target/Sparc/SparcTargetMachine.cpp | 9 +- lib/Target/Sparc/SparcTargetMachine.h | 6 + lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp | 8 +- lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 475 +- lib/Target/SystemZ/CMakeLists.txt | 9 +- lib/Target/SystemZ/Disassembler/CMakeLists.txt | 7 + lib/Target/SystemZ/Disassembler/LLVMBuild.txt | 23 + lib/Target/SystemZ/Disassembler/Makefile | 16 + .../SystemZ/Disassembler/SystemZDisassembler.cpp | 323 + .../SystemZ/InstPrinter/SystemZInstPrinter.cpp | 23 +- .../SystemZ/InstPrinter/SystemZInstPrinter.h | 3 +- lib/Target/SystemZ/LLVMBuild.txt | 3 +- .../SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp | 49 +- .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 4 +- lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h | 7 +- .../SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp | 114 +- .../SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp | 81 +- .../SystemZ/MCTargetDesc/SystemZMCTargetDesc.h | 38 +- lib/Target/SystemZ/Makefile | 3 +- lib/Target/SystemZ/README.txt | 65 +- lib/Target/SystemZ/SystemZ.h | 42 +- lib/Target/SystemZ/SystemZ.td | 7 +- lib/Target/SystemZ/SystemZAsmPrinter.cpp | 136 +- lib/Target/SystemZ/SystemZCallingConv.td | 4 +- lib/Target/SystemZ/SystemZConstantPoolValue.cpp | 2 +- lib/Target/SystemZ/SystemZElimCompare.cpp | 471 + lib/Target/SystemZ/SystemZFrameLowering.cpp | 108 +- lib/Target/SystemZ/SystemZFrameLowering.h | 27 +- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 604 +- lib/Target/SystemZ/SystemZISelLowering.cpp | 1523 +- lib/Target/SystemZ/SystemZISelLowering.h | 139 +- lib/Target/SystemZ/SystemZInstrFP.td | 320 +- lib/Target/SystemZ/SystemZInstrFormats.td | 1242 +- lib/Target/SystemZ/SystemZInstrInfo.cpp | 907 +- lib/Target/SystemZ/SystemZInstrInfo.h | 150 +- lib/Target/SystemZ/SystemZInstrInfo.td | 1226 +- lib/Target/SystemZ/SystemZLongBranch.cpp | 462 + lib/Target/SystemZ/SystemZMCInstLower.cpp | 116 +- lib/Target/SystemZ/SystemZMCInstLower.h | 15 +- lib/Target/SystemZ/SystemZMachineFunctionInfo.cpp | 17 + lib/Target/SystemZ/SystemZMachineFunctionInfo.h | 12 +- lib/Target/SystemZ/SystemZOperands.td | 153 +- lib/Target/SystemZ/SystemZOperators.td | 208 +- lib/Target/SystemZ/SystemZPatterns.td | 99 +- lib/Target/SystemZ/SystemZProcessors.td | 46 + lib/Target/SystemZ/SystemZRegisterInfo.cpp | 37 +- lib/Target/SystemZ/SystemZRegisterInfo.h | 16 +- lib/Target/SystemZ/SystemZRegisterInfo.td | 71 +- lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp | 293 + lib/Target/SystemZ/SystemZSelectionDAGInfo.h | 80 + lib/Target/SystemZ/SystemZShortenInst.cpp | 163 + lib/Target/SystemZ/SystemZSubtarget.cpp | 15 +- lib/Target/SystemZ/SystemZSubtarget.h | 22 + lib/Target/SystemZ/SystemZTargetMachine.cpp | 50 +- lib/Target/SystemZ/SystemZTargetMachine.h | 4 +- lib/Target/Target.cpp | 8 + lib/Target/TargetLibraryInfo.cpp | 44 +- lib/Target/TargetLoweringObjectFile.cpp | 20 +- lib/Target/TargetMachine.cpp | 6 +- lib/Target/TargetMachineC.cpp | 56 +- lib/Target/TargetSubtargetInfo.cpp | 19 + lib/Target/X86/AsmParser/X86AsmParser.cpp | 420 +- lib/Target/X86/CMakeLists.txt | 2 +- lib/Target/X86/Disassembler/X86Disassembler.cpp | 145 +- .../X86/Disassembler/X86DisassemblerDecoder.c | 267 +- .../X86/Disassembler/X86DisassemblerDecoder.h | 106 +- .../Disassembler/X86DisassemblerDecoderCommon.h | 165 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 37 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.h | 22 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp | 32 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.h | 52 +- lib/Target/X86/MCTargetDesc/CMakeLists.txt | 2 + lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 401 +- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 82 +- lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 22 +- .../X86/MCTargetDesc/X86ELFRelocationInfo.cpp | 135 + lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 6 +- lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h | 3 +- lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 335 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 35 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 13 +- .../X86/MCTargetDesc/X86MachORelocationInfo.cpp | 116 + .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 177 +- .../X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp | 2 +- lib/Target/X86/README-SSE.txt | 31 - lib/Target/X86/X86.td | 71 +- lib/Target/X86/X86AsmPrinter.cpp | 86 +- lib/Target/X86/X86AsmPrinter.h | 20 +- lib/Target/X86/X86CallingConv.h | 35 + lib/Target/X86/X86CallingConv.td | 102 +- lib/Target/X86/X86CodeEmitter.cpp | 47 +- lib/Target/X86/X86FastISel.cpp | 488 +- lib/Target/X86/X86FixupLEAs.cpp | 11 +- lib/Target/X86/X86FloatingPoint.cpp | 18 +- lib/Target/X86/X86FrameLowering.cpp | 337 +- lib/Target/X86/X86FrameLowering.h | 27 - lib/Target/X86/X86ISelDAGToDAG.cpp | 226 +- lib/Target/X86/X86ISelLowering.cpp | 3138 ++- lib/Target/X86/X86ISelLowering.h | 136 +- lib/Target/X86/X86InstrAVX512.td | 3526 +++ lib/Target/X86/X86InstrArithmetic.td | 250 +- lib/Target/X86/X86InstrCompiler.td | 130 +- lib/Target/X86/X86InstrControl.td | 5 +- lib/Target/X86/X86InstrExtension.td | 68 +- lib/Target/X86/X86InstrFMA.td | 77 +- lib/Target/X86/X86InstrFPStack.td | 30 +- lib/Target/X86/X86InstrFormats.td | 181 +- lib/Target/X86/X86InstrFragmentsSIMD.td | 141 +- lib/Target/X86/X86InstrInfo.cpp | 1000 +- lib/Target/X86/X86InstrInfo.h | 26 +- lib/Target/X86/X86InstrInfo.td | 654 +- lib/Target/X86/X86InstrMMX.td | 93 +- lib/Target/X86/X86InstrSSE.td | 1833 +- lib/Target/X86/X86InstrSVM.td | 18 +- lib/Target/X86/X86InstrShiftRotate.td | 136 +- lib/Target/X86/X86InstrSystem.td | 76 +- lib/Target/X86/X86InstrTSX.td | 7 + lib/Target/X86/X86InstrXOP.td | 146 +- lib/Target/X86/X86JITInfo.cpp | 3 +- lib/Target/X86/X86MCInstLower.cpp | 270 +- lib/Target/X86/X86RegisterInfo.cpp | 89 +- lib/Target/X86/X86RegisterInfo.h | 10 +- lib/Target/X86/X86RegisterInfo.td | 92 +- lib/Target/X86/X86SchedHaswell.td | 14 +- lib/Target/X86/X86SchedSandyBridge.td | 13 +- lib/Target/X86/X86Schedule.td | 73 +- lib/Target/X86/X86ScheduleAtom.td | 41 +- lib/Target/X86/X86ScheduleSLM.td | 668 + lib/Target/X86/X86SelectionDAGInfo.cpp | 6 +- lib/Target/X86/X86SelectionDAGInfo.h | 4 +- lib/Target/X86/X86Subtarget.cpp | 60 +- lib/Target/X86/X86Subtarget.h | 51 +- lib/Target/X86/X86TargetMachine.cpp | 10 +- lib/Target/X86/X86TargetObjectFile.cpp | 10 +- lib/Target/X86/X86TargetObjectFile.h | 3 + lib/Target/X86/X86TargetTransformInfo.cpp | 234 +- lib/Target/X86/X86VZeroUpper.cpp | 45 +- lib/Target/XCore/CMakeLists.txt | 3 +- .../XCore/Disassembler/XCoreDisassembler.cpp | 8 +- lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp | 10 +- lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h | 6 +- .../XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 10 +- lib/Target/XCore/README.txt | 1 + lib/Target/XCore/XCore.h | 2 + lib/Target/XCore/XCoreAsmPrinter.cpp | 80 +- lib/Target/XCore/XCoreFrameLowering.cpp | 107 +- lib/Target/XCore/XCoreISelDAGToDAG.cpp | 14 +- lib/Target/XCore/XCoreISelLowering.cpp | 200 +- lib/Target/XCore/XCoreISelLowering.h | 24 +- lib/Target/XCore/XCoreInstrInfo.cpp | 17 +- lib/Target/XCore/XCoreInstrInfo.h | 7 +- lib/Target/XCore/XCoreInstrInfo.td | 26 +- lib/Target/XCore/XCoreLowerThreadLocal.cpp | 114 +- lib/Target/XCore/XCoreMCInstLower.cpp | 2 +- lib/Target/XCore/XCoreRegisterInfo.cpp | 6 +- lib/Target/XCore/XCoreRegisterInfo.h | 4 +- lib/Target/XCore/XCoreTargetMachine.cpp | 9 + lib/Target/XCore/XCoreTargetMachine.h | 2 + lib/Target/XCore/XCoreTargetTransformInfo.cpp | 83 + lib/Transforms/Hello/Hello.cpp | 2 +- lib/Transforms/IPO/ArgumentPromotion.cpp | 31 +- lib/Transforms/IPO/ConstantMerge.cpp | 11 +- lib/Transforms/IPO/DeadArgumentElimination.cpp | 138 +- lib/Transforms/IPO/ExtractGV.cpp | 54 +- lib/Transforms/IPO/FunctionAttrs.cpp | 437 +- lib/Transforms/IPO/GlobalDCE.cpp | 3 + lib/Transforms/IPO/GlobalOpt.cpp | 514 +- lib/Transforms/IPO/InlineAlways.cpp | 2 +- lib/Transforms/IPO/InlineSimple.cpp | 4 +- lib/Transforms/IPO/Inliner.cpp | 27 +- lib/Transforms/IPO/Internalize.cpp | 136 +- lib/Transforms/IPO/MergeFunctions.cpp | 77 +- lib/Transforms/IPO/PassManagerBuilder.cpp | 62 +- lib/Transforms/IPO/PruneEH.cpp | 14 +- lib/Transforms/IPO/StripSymbols.cpp | 231 +- lib/Transforms/InstCombine/InstCombine.h | 16 +- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 49 +- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 263 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 46 +- lib/Transforms/InstCombine/InstCombineCasts.cpp | 168 +- lib/Transforms/InstCombine/InstCombineCompares.cpp | 392 +- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 30 +- .../InstCombine/InstCombineMulDivRem.cpp | 385 +- lib/Transforms/InstCombine/InstCombinePHI.cpp | 14 +- lib/Transforms/InstCombine/InstCombineSelect.cpp | 15 +- .../InstCombine/InstCombineSimplifyDemanded.cpp | 28 +- .../InstCombine/InstCombineVectorOps.cpp | 321 +- lib/Transforms/InstCombine/InstCombineWorklist.h | 9 +- .../InstCombine/InstructionCombining.cpp | 114 +- .../Instrumentation/AddressSanitizer.cpp | 366 +- lib/Transforms/Instrumentation/BlackList.cpp | 126 - lib/Transforms/Instrumentation/BoundsChecking.cpp | 6 +- lib/Transforms/Instrumentation/CMakeLists.txt | 7 +- .../Instrumentation/DataFlowSanitizer.cpp | 1397 + lib/Transforms/Instrumentation/DebugIR.cpp | 618 + lib/Transforms/Instrumentation/DebugIR.h | 99 + lib/Transforms/Instrumentation/EdgeProfiling.cpp | 117 - lib/Transforms/Instrumentation/GCOVProfiling.cpp | 93 +- lib/Transforms/Instrumentation/Instrumentation.cpp | 4 +- lib/Transforms/Instrumentation/MemorySanitizer.cpp | 537 +- .../Instrumentation/OptimalEdgeProfiling.cpp | 225 - lib/Transforms/Instrumentation/PathProfiling.cpp | 1424 -- lib/Transforms/Instrumentation/ProfilingUtils.cpp | 169 - lib/Transforms/Instrumentation/ProfilingUtils.h | 36 - lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 18 +- lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h | 186 + lib/Transforms/ObjCARC/DependencyAnalysis.h | 2 +- lib/Transforms/ObjCARC/ObjCARC.h | 6 +- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp | 2 +- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.h | 2 +- lib/Transforms/ObjCARC/ObjCARCContract.cpp | 110 +- lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 760 +- lib/Transforms/ObjCARC/ObjCARCUtil.cpp | 4 +- lib/Transforms/ObjCARC/ProvenanceAnalysis.h | 2 +- lib/Transforms/Scalar/ADCE.cpp | 2 +- lib/Transforms/Scalar/BasicBlockPlacement.cpp | 152 - lib/Transforms/Scalar/CMakeLists.txt | 7 +- lib/Transforms/Scalar/CodeGenPrepare.cpp | 105 +- lib/Transforms/Scalar/EarlyCSE.cpp | 10 - lib/Transforms/Scalar/FlattenCFGPass.cpp | 79 + lib/Transforms/Scalar/GVN.cpp | 252 +- lib/Transforms/Scalar/GlobalMerge.cpp | 18 +- lib/Transforms/Scalar/IndVarSimplify.cpp | 91 +- lib/Transforms/Scalar/JumpThreading.cpp | 89 +- lib/Transforms/Scalar/LoopDeletion.cpp | 10 +- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 74 +- lib/Transforms/Scalar/LoopRerollPass.cpp | 1184 + lib/Transforms/Scalar/LoopStrengthReduce.cpp | 136 +- lib/Transforms/Scalar/LoopUnrollPass.cpp | 42 +- lib/Transforms/Scalar/LoopUnswitch.cpp | 229 +- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 23 +- lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp | 156 + lib/Transforms/Scalar/Reassociate.cpp | 41 +- lib/Transforms/Scalar/SCCP.cpp | 14 +- lib/Transforms/Scalar/SROA.cpp | 2802 +- lib/Transforms/Scalar/SampleProfile.cpp | 479 + lib/Transforms/Scalar/Scalar.cpp | 16 +- lib/Transforms/Scalar/ScalarReplAggregates.cpp | 51 +- lib/Transforms/Scalar/SimplifyCFGPass.cpp | 194 +- lib/Transforms/Scalar/SimplifyLibCalls.cpp | 247 - lib/Transforms/Scalar/StructurizeCFG.cpp | 906 + lib/Transforms/Scalar/TailRecursionElimination.cpp | 170 +- lib/Transforms/Utils/BasicBlockUtils.cpp | 175 +- lib/Transforms/Utils/BreakCriticalEdges.cpp | 43 +- lib/Transforms/Utils/CMakeLists.txt | 3 + lib/Transforms/Utils/CloneFunction.cpp | 5 +- lib/Transforms/Utils/CodeExtractor.cpp | 7 +- lib/Transforms/Utils/DemoteRegToStack.cpp | 1 + lib/Transforms/Utils/FlattenCFG.cpp | 486 + lib/Transforms/Utils/GlobalStatus.cpp | 183 + lib/Transforms/Utils/InlineFunction.cpp | 3 +- lib/Transforms/Utils/LCSSA.cpp | 15 +- lib/Transforms/Utils/Local.cpp | 473 +- lib/Transforms/Utils/LoopSimplify.cpp | 23 +- lib/Transforms/Utils/LoopUnroll.cpp | 8 +- lib/Transforms/Utils/LowerExpectIntrinsic.cpp | 2 +- lib/Transforms/Utils/LowerInvoke.cpp | 21 +- lib/Transforms/Utils/LowerSwitch.cpp | 62 +- lib/Transforms/Utils/MetaRenamer.cpp | 2 +- lib/Transforms/Utils/ModuleUtils.cpp | 18 + lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 1082 +- lib/Transforms/Utils/SSAUpdater.cpp | 50 +- lib/Transforms/Utils/SimplifyCFG.cpp | 311 +- lib/Transforms/Utils/SimplifyIndVar.cpp | 2 +- lib/Transforms/Utils/SimplifyLibCalls.cpp | 323 +- lib/Transforms/Utils/SpecialCaseList.cpp | 222 + lib/Transforms/Utils/ValueMapper.cpp | 29 +- lib/Transforms/Vectorize/BBVectorize.cpp | 90 +- lib/Transforms/Vectorize/CMakeLists.txt | 1 - lib/Transforms/Vectorize/LoopVectorize.cpp | 2795 +- lib/Transforms/Vectorize/SLPVectorizer.cpp | 2529 +- lib/Transforms/Vectorize/VecUtils.cpp | 730 - lib/Transforms/Vectorize/VecUtils.h | 164 - projects/CMakeLists.txt | 9 +- projects/Makefile | 3 + projects/sample/Makefile.llvm.rules | 264 +- projects/sample/autoconf/config.guess | 3 + projects/sample/autoconf/configure.ac | 82 +- projects/sample/autoconf/m4/libtool.m4 | 2 +- projects/sample/autoconf/m4/link_options.m4 | 9 +- projects/sample/autoconf/m4/ltdl.m4 | 15 - projects/sample/configure | 929 +- runtime/CMakeLists.txt | 5 - runtime/LLVMBuild.txt | 21 - runtime/Makefile | 31 - runtime/README.txt | 4 - runtime/libprofile/BasicBlockTracing.c | 67 - runtime/libprofile/CMakeLists.txt | 19 - runtime/libprofile/CommonProfiling.c | 173 - runtime/libprofile/EdgeProfiling.c | 45 - runtime/libprofile/Makefile | 56 - runtime/libprofile/OptimalEdgeProfiling.c | 45 - runtime/libprofile/PathProfiling.c | 270 - runtime/libprofile/Profiling.h | 36 - test/.clang-format | 2 + test/Analysis/BasicAA/full-store-partial-alias.ll | 6 +- test/Analysis/BasicAA/gep-alias.ll | 61 +- test/Analysis/BasicAA/global-size.ll | 18 +- test/Analysis/BasicAA/lit.local.cfg | 1 - test/Analysis/BasicAA/noalias-geps.ll | 2 + test/Analysis/BasicAA/noalias-param.ll | 23 + test/Analysis/BlockFrequencyInfo/basic.ll | 74 +- test/Analysis/BlockFrequencyInfo/lit.local.cfg | 1 - test/Analysis/BranchProbabilityInfo/basic.ll | 97 + test/Analysis/BranchProbabilityInfo/lit.local.cfg | 1 - test/Analysis/CallGraph/lit.local.cfg | 1 - test/Analysis/CallGraph/no-intrinsics.ll | 2 +- test/Analysis/CostModel/ARM/lit.local.cfg | 2 - test/Analysis/CostModel/ARM/select.ll | 8 + test/Analysis/CostModel/PowerPC/lit.local.cfg | 2 - test/Analysis/CostModel/X86/cast.ll | 8 +- test/Analysis/CostModel/X86/div.ll | 32 + test/Analysis/CostModel/X86/intrinsic-cost.ll | 28 + test/Analysis/CostModel/X86/lit.local.cfg | 2 - test/Analysis/CostModel/X86/load_store.ll | 19 + test/Analysis/CostModel/X86/reduction.ll | 365 + test/Analysis/CostModel/lit.local.cfg | 1 - test/Analysis/Delinearization/a.ll | 74 + test/Analysis/Delinearization/himeno_1.ll | 102 + test/Analysis/Delinearization/himeno_2.ll | 102 + test/Analysis/Delinearization/lit.local.cfg | 1 + .../multidim_ivs_and_integer_offsets_3d.ll | 68 + .../multidim_ivs_and_integer_offsets_nts_3d.ll | 72 + .../multidim_ivs_and_parameteric_offsets_3d.ll | 68 + .../Delinearization/multidim_only_ivs_2d.ll | 46 + .../Delinearization/multidim_only_ivs_2d_nested.ll | 78 + .../Delinearization/multidim_only_ivs_3d.ll | 65 + .../Delinearization/multidim_only_ivs_3d_cast.ll | 75 + test/Analysis/DependenceAnalysis/Banerjee.ll | 14 +- test/Analysis/DependenceAnalysis/GCD.ll | 10 + test/Analysis/DependenceAnalysis/Invariant.ll | 40 + test/Analysis/DependenceAnalysis/SymbolicRDIV.ll | 7 + test/Analysis/DependenceAnalysis/lit.local.cfg | 1 - test/Analysis/Dominators/lit.local.cfg | 1 - test/Analysis/GlobalsModRef/lit.local.cfg | 1 - test/Analysis/Lint/check-zero-divide.ll | 78 + test/Analysis/Lint/lit.local.cfg | 1 + .../Analysis/LoopInfo/2003-05-15-NestingProblem.ll | 5 +- test/Analysis/LoopInfo/lit.local.cfg | 1 - .../MemoryDependenceAnalysis/lit.local.cfg | 1 - test/Analysis/PostDominators/lit.local.cfg | 1 - test/Analysis/PostDominators/pr1098.ll | 3 +- test/Analysis/Profiling/edge-profiling.ll | 139 - test/Analysis/Profiling/lit.local.cfg | 11 - test/Analysis/Profiling/load-branch-weights-ifs.ll | 122 - .../Profiling/load-branch-weights-loops.ll | 188 - .../Profiling/load-branch-weights-switches.ll | 165 - test/Analysis/Profiling/profiling-tool-chain.ll | 212 - test/Analysis/RegionInfo/lit.local.cfg | 1 - .../ScalarEvolution/2007-07-15-NegativeStride.ll | 5 +- .../2007-08-06-MisinterpretBranch.ll | 4 +- .../ScalarEvolution/2007-08-06-Unsigned.ll | 4 +- .../ScalarEvolution/2007-09-27-LargeStepping.ll | 5 +- .../ScalarEvolution/2007-11-14-SignedAddRec.ll | 4 +- .../2008-02-11-ReversedCondition.ll | 4 +- test/Analysis/ScalarEvolution/2008-02-15-UMax.ll | 4 +- .../2008-05-25-NegativeStepToZero.ll | 5 +- .../ScalarEvolution/2008-07-12-UnneededSelect1.ll | 5 +- .../ScalarEvolution/2008-07-12-UnneededSelect2.ll | 5 +- .../ScalarEvolution/2008-07-19-InfiniteLoop.ll | 5 +- .../ScalarEvolution/2008-07-19-WrappingIV.ll | 5 +- .../ScalarEvolution/2008-11-18-LessThanOrEqual.ll | 5 +- .../Analysis/ScalarEvolution/2008-11-18-Stride1.ll | 7 +- .../Analysis/ScalarEvolution/2008-11-18-Stride2.ll | 7 +- .../ScalarEvolution/2008-12-08-FiniteSGE.ll | 4 +- .../ScalarEvolution/2008-12-14-StrideAndSigned.ll | 5 +- .../ScalarEvolution/2008-12-15-DontUseSDiv.ll | 5 +- .../2009-01-02-SignedNegativeStride.ll | 5 +- .../ScalarEvolution/2009-04-22-TruncCast.ll | 18 + .../ScalarEvolution/2009-05-09-PointerEdgeCount.ll | 5 +- .../ScalarEvolution/2011-04-26-FoldAddRec.ll | 2 +- .../ScalarEvolution/SolveQuadraticEquation.ll | 3 +- test/Analysis/ScalarEvolution/and-xor.ll | 7 +- test/Analysis/ScalarEvolution/avoid-smax-0.ll | 4 +- test/Analysis/ScalarEvolution/div-overflow.ll | 5 +- test/Analysis/ScalarEvolution/do-loop.ll | 4 +- test/Analysis/ScalarEvolution/lit.local.cfg | 1 - .../max-trip-count-address-space.ll | 68 + test/Analysis/ScalarEvolution/nsw.ll | 40 +- test/Analysis/ScalarEvolution/smax.ll | 8 +- test/Analysis/ScalarEvolution/trip-count.ll | 4 +- test/Analysis/ScalarEvolution/trip-count10.ll | 31 +- test/Analysis/ScalarEvolution/trip-count11.ll | 28 +- test/Analysis/ScalarEvolution/trip-count2.ll | 4 +- test/Analysis/ScalarEvolution/trip-count3.ll | 6 +- test/Analysis/ScalarEvolution/trip-count4.ll | 5 +- test/Analysis/ScalarEvolution/trip-count6.ll | 5 +- test/Analysis/ScalarEvolution/trip-count7.ll | 5 +- test/Analysis/ScalarEvolution/trip-count8.ll | 5 +- test/Analysis/ScalarEvolution/trip-count9.ll | 47 +- test/Analysis/ScalarEvolution/xor-and.ll | 5 +- test/Analysis/ScalarEvolution/zext-wrap.ll | 3 +- test/Analysis/TypeBasedAliasAnalysis/PR17620.ll | 45 + test/Analysis/TypeBasedAliasAnalysis/aliastest.ll | 17 +- .../TypeBasedAliasAnalysis/argument-promotion.ll | 14 +- test/Analysis/TypeBasedAliasAnalysis/dse.ll | 17 +- .../TypeBasedAliasAnalysis/dynamic-indices.ll | 16 +- .../TypeBasedAliasAnalysis/functionattrs.ll | 7 +- .../gvn-nonlocal-type-mismatch.ll | 12 +- test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll | 6 +- test/Analysis/TypeBasedAliasAnalysis/licm.ll | 14 +- test/Analysis/TypeBasedAliasAnalysis/lit.local.cfg | 1 - test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll | 10 +- .../TypeBasedAliasAnalysis/placement-tbaa.ll | 44 +- test/Analysis/TypeBasedAliasAnalysis/precedence.ll | 12 +- test/Analysis/TypeBasedAliasAnalysis/sink.ll | 10 +- test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll | 4 +- test/Archive/GNU.a | Bin 4210 -> 0 bytes test/Archive/IsNAN.o | Bin 2280 -> 0 bytes test/Archive/MacOSX.a | Bin 4166 -> 0 bytes test/Archive/README.txt | 24 - test/Archive/SVR4.a | Bin 4214 -> 0 bytes test/Archive/check_binary_output.ll | 4 - test/Archive/evenlen | 1 - test/Archive/extract.ll | 16 - test/Archive/lit.local.cfg | 1 - test/Archive/oddlen | 1 - test/Archive/toc_GNU.ll | 8 - test/Archive/toc_MacOSX.ll | 9 - test/Archive/toc_SVR4.ll | 8 - test/Archive/toc_xpg4.ll | 8 - test/Archive/very_long_bytecode_file_name.bc | Bin 1465 -> 0 bytes test/Archive/xpg4.a | Bin 4214 -> 0 bytes .../2010-02-05-FunctionLocalMetadataBecomesNull.ll | 14 +- test/Assembler/ConstantExprFoldCast.ll | 2 + test/Assembler/ConstantExprNoFold.ll | 3 + test/Assembler/attribute-builtin.ll | 50 + test/Assembler/auto_upgrade_intrinsics.ll | 15 + test/Assembler/functionlocal-metadata.ll | 32 +- test/Assembler/lit.local.cfg | 1 - test/Bindings/Ocaml/analysis.ml | 5 +- test/Bindings/Ocaml/bitreader.ml | 5 +- test/Bindings/Ocaml/bitwriter.ml | 5 +- test/Bindings/Ocaml/executionengine.ml | 11 +- test/Bindings/Ocaml/ext_exc.ml | 5 +- test/Bindings/Ocaml/ipo_opts.ml | 13 +- test/Bindings/Ocaml/irreader.ml | 59 + test/Bindings/Ocaml/linker.ml | 63 + test/Bindings/Ocaml/lit.local.cfg | 3 +- test/Bindings/Ocaml/passmgr_builder.ml | 64 + test/Bindings/Ocaml/scalar_opts.ml | 13 +- test/Bindings/Ocaml/target.ml | 104 +- test/Bindings/Ocaml/vectorize_opts.ml | 56 + test/Bindings/Ocaml/vmcore.ml | 744 +- test/Bindings/llvm-c/calc.test | 15 + test/Bindings/llvm-c/disassemble.test | 29 + test/Bindings/llvm-c/functions.ll | 31 + test/Bindings/llvm-c/globals.ll | 7 + test/Bindings/llvm-c/lit.local.cfg | 5 + test/Bitcode/2012-05-07-SwitchInstRangesSupport.ll | 33 - test/Bitcode/attributes-3.3.ll | 236 + test/Bitcode/attributes-3.3.ll.bc | Bin 0 -> 1592 bytes test/Bitcode/attributes.ll | 39 + test/Bitcode/case-ranges-3.3.ll | 67 + test/Bitcode/case-ranges-3.3.ll.bc | Bin 0 -> 560 bytes test/Bitcode/drop-debug-info.ll | 26 + test/Bitcode/extractelement.ll | 2 +- test/Bitcode/invalid.ll | 7 + test/Bitcode/invalid.ll.bc | Bin 0 -> 332 bytes test/Bitcode/lit.local.cfg | 1 - test/Bitcode/metadata-2.ll | 2 +- test/Bitcode/metadata.ll | 3 +- test/Bitcode/null-type.ll | 5 +- test/Bitcode/select.ll | 9 + test/Bitcode/shuffle.ll | 2 +- test/Bitcode/upgrade-tbaa.ll | 23 + test/BugPoint/crash-narrowfunctiontest.ll | 1 - test/BugPoint/lit.local.cfg | 1 - test/BugPoint/metadata.ll | 18 +- test/BugPoint/remove_arguments_test.ll | 1 - test/CMakeLists.txt | 34 +- test/CodeGen/AArch64/adc.ll | 8 +- test/CodeGen/AArch64/addsub-shifted.ll | 10 +- test/CodeGen/AArch64/addsub.ll | 10 +- test/CodeGen/AArch64/addsub_ext.ll | 8 +- test/CodeGen/AArch64/adrp-relocation.ll | 27 - test/CodeGen/AArch64/alloca.ll | 43 +- test/CodeGen/AArch64/analyze-branch.ll | 20 +- test/CodeGen/AArch64/atomic-ops-not-barriers.ll | 2 +- test/CodeGen/AArch64/atomic-ops.ll | 116 +- test/CodeGen/AArch64/basic-pic.ll | 28 +- test/CodeGen/AArch64/bitfield-insert-0.ll | 2 +- test/CodeGen/AArch64/bitfield-insert.ll | 20 +- test/CodeGen/AArch64/bitfield.ll | 22 +- test/CodeGen/AArch64/blockaddress.ll | 2 +- test/CodeGen/AArch64/breg.ll | 2 +- test/CodeGen/AArch64/callee-save.ll | 2 +- test/CodeGen/AArch64/code-model-large-abs.ll | 10 +- test/CodeGen/AArch64/compare-branch.ll | 4 +- test/CodeGen/AArch64/complex-copy-noneon.ll | 21 + test/CodeGen/AArch64/cond-sel.ll | 25 +- test/CodeGen/AArch64/directcond.ll | 16 +- test/CodeGen/AArch64/dp-3source.ll | 36 +- test/CodeGen/AArch64/dp1.ll | 28 +- test/CodeGen/AArch64/dp2.ll | 30 +- test/CodeGen/AArch64/elf-extern.ll | 17 - test/CodeGen/AArch64/extern-weak.ll | 2 +- test/CodeGen/AArch64/extract.ll | 10 +- test/CodeGen/AArch64/fastcc-reserved.ll | 4 +- test/CodeGen/AArch64/fastcc.ll | 12 +- test/CodeGen/AArch64/fcmp.ll | 4 +- test/CodeGen/AArch64/fcvt-fixed.ll | 8 +- test/CodeGen/AArch64/fcvt-int.ll | 56 +- test/CodeGen/AArch64/flags-multiuse.ll | 2 +- test/CodeGen/AArch64/floatdp_1source.ll | 6 +- test/CodeGen/AArch64/floatdp_2source.ll | 4 +- test/CodeGen/AArch64/fp-cond-sel.ll | 2 +- test/CodeGen/AArch64/fp-dp3.ll | 59 +- test/CodeGen/AArch64/fp128-folding.ll | 4 +- test/CodeGen/AArch64/fp128.ll | 47 +- test/CodeGen/AArch64/fpimm.ll | 14 +- test/CodeGen/AArch64/frameaddr.ll | 20 + test/CodeGen/AArch64/func-argpassing.ll | 52 +- test/CodeGen/AArch64/func-calls.ll | 30 +- test/CodeGen/AArch64/global-alignment.ll | 10 +- test/CodeGen/AArch64/got-abuse.ll | 2 +- test/CodeGen/AArch64/i128-align.ll | 6 +- test/CodeGen/AArch64/illegal-float-ops.ll | 46 +- test/CodeGen/AArch64/init-array.ll | 2 +- .../CodeGen/AArch64/inline-asm-constraints-badI.ll | 2 +- .../CodeGen/AArch64/inline-asm-constraints-badK.ll | 2 +- .../AArch64/inline-asm-constraints-badK2.ll | 2 +- .../CodeGen/AArch64/inline-asm-constraints-badL.ll | 2 +- test/CodeGen/AArch64/inline-asm-constraints.ll | 48 +- test/CodeGen/AArch64/inline-asm-modifiers.ll | 64 +- test/CodeGen/AArch64/jump-table.ll | 17 - test/CodeGen/AArch64/large-consts.ll | 13 + test/CodeGen/AArch64/large-frame.ll | 11 +- test/CodeGen/AArch64/ldst-regoffset.ll | 33 +- test/CodeGen/AArch64/ldst-unscaledimm.ll | 15 +- test/CodeGen/AArch64/ldst-unsignedimm.ll | 15 +- test/CodeGen/AArch64/lit.local.cfg | 2 - test/CodeGen/AArch64/literal_pools.ll | 20 +- test/CodeGen/AArch64/local_vars.ll | 4 +- test/CodeGen/AArch64/logical-imm.ll | 8 +- test/CodeGen/AArch64/logical_shifted_reg.ll | 6 +- test/CodeGen/AArch64/logical_shifted_reg.s | 208 - test/CodeGen/AArch64/movw-consts.ll | 36 +- test/CodeGen/AArch64/movw-shift-encoding.ll | 14 + test/CodeGen/AArch64/neon-2velem-high.ll | 331 + test/CodeGen/AArch64/neon-2velem.ll | 2550 ++ test/CodeGen/AArch64/neon-3vdiff.ll | 1806 ++ test/CodeGen/AArch64/neon-aba-abd.ll | 236 + test/CodeGen/AArch64/neon-across.ll | 476 + test/CodeGen/AArch64/neon-add-pairwise.ll | 92 + test/CodeGen/AArch64/neon-add-sub.ll | 237 + test/CodeGen/AArch64/neon-bitcast.ll | 574 + test/CodeGen/AArch64/neon-bitwise-instructions.ll | 594 + test/CodeGen/AArch64/neon-bsl.ll | 222 + test/CodeGen/AArch64/neon-compare-instructions.ll | 1926 ++ test/CodeGen/AArch64/neon-copy.ll | 615 + test/CodeGen/AArch64/neon-crypto.ll | 149 + test/CodeGen/AArch64/neon-diagnostics.ll | 24 + test/CodeGen/AArch64/neon-extract.ll | 190 + test/CodeGen/AArch64/neon-facge-facgt.ll | 56 + test/CodeGen/AArch64/neon-fma.ll | 112 + test/CodeGen/AArch64/neon-frsqrt-frecp.ll | 54 + test/CodeGen/AArch64/neon-halving-add-sub.ll | 207 + test/CodeGen/AArch64/neon-max-min-pairwise.ll | 310 + test/CodeGen/AArch64/neon-max-min.ll | 310 + test/CodeGen/AArch64/neon-misc-scalar.ll | 60 + test/CodeGen/AArch64/neon-misc.ll | 1799 ++ test/CodeGen/AArch64/neon-mla-mls.ll | 88 + test/CodeGen/AArch64/neon-mov.ll | 217 + test/CodeGen/AArch64/neon-mul-div.ll | 181 + test/CodeGen/AArch64/neon-perm.ll | 1693 ++ test/CodeGen/AArch64/neon-rounding-halving-add.ll | 105 + test/CodeGen/AArch64/neon-rounding-shift.ll | 121 + test/CodeGen/AArch64/neon-saturating-add-sub.ll | 241 + .../AArch64/neon-saturating-rounding-shift.ll | 121 + test/CodeGen/AArch64/neon-saturating-shift.ll | 121 + test/CodeGen/AArch64/neon-scalar-abs.ll | 61 + test/CodeGen/AArch64/neon-scalar-add-sub.ll | 50 + test/CodeGen/AArch64/neon-scalar-by-elem-fma.ll | 108 + test/CodeGen/AArch64/neon-scalar-by-elem-mul.ll | 124 + test/CodeGen/AArch64/neon-scalar-compare.ll | 343 + test/CodeGen/AArch64/neon-scalar-copy.ll | 88 + test/CodeGen/AArch64/neon-scalar-cvt.ll | 137 + test/CodeGen/AArch64/neon-scalar-extract-narrow.ll | 104 + test/CodeGen/AArch64/neon-scalar-fabd.ll | 26 + test/CodeGen/AArch64/neon-scalar-fcvt.ll | 255 + test/CodeGen/AArch64/neon-scalar-fp-compare.ll | 328 + test/CodeGen/AArch64/neon-scalar-mul.ll | 143 + test/CodeGen/AArch64/neon-scalar-neg.ll | 61 + test/CodeGen/AArch64/neon-scalar-recip.ll | 116 + .../CodeGen/AArch64/neon-scalar-reduce-pairwise.ll | 247 + test/CodeGen/AArch64/neon-scalar-rounding-shift.ll | 39 + .../AArch64/neon-scalar-saturating-add-sub.ll | 242 + .../neon-scalar-saturating-rounding-shift.ll | 94 + .../AArch64/neon-scalar-saturating-shift.ll | 88 + test/CodeGen/AArch64/neon-scalar-shift-imm.ll | 531 + test/CodeGen/AArch64/neon-scalar-shift.ll | 38 + test/CodeGen/AArch64/neon-shift-left-long.ll | 193 + test/CodeGen/AArch64/neon-shift.ll | 171 + test/CodeGen/AArch64/neon-simd-ldst-multi-elem.ll | 2314 ++ test/CodeGen/AArch64/neon-simd-ldst-one.ll | 2113 ++ test/CodeGen/AArch64/neon-simd-ldst.ll | 164 + .../AArch64/neon-simd-post-ldst-multi-elem.ll | 354 + test/CodeGen/AArch64/neon-simd-post-ldst-one.ll | 319 + test/CodeGen/AArch64/neon-simd-shift.ll | 1556 ++ test/CodeGen/AArch64/neon-simd-tbl.ll | 828 + test/CodeGen/AArch64/neon-simd-vget.ll | 225 + test/CodeGen/AArch64/pic-eh-stubs.ll | 2 +- test/CodeGen/AArch64/regress-bitcast-formals.ll | 2 +- test/CodeGen/AArch64/regress-fp128-livein.ll | 17 + test/CodeGen/AArch64/regress-tail-livereg.ll | 4 +- test/CodeGen/AArch64/regress-tblgen-chains.ll | 2 +- .../AArch64/regress-w29-reserved-with-fp.ll | 17 +- test/CodeGen/AArch64/returnaddr.ll | 21 + test/CodeGen/AArch64/setcc-takes-i32.ll | 4 +- test/CodeGen/AArch64/sibling-call.ll | 20 +- test/CodeGen/AArch64/sincos-expansion.ll | 8 +- test/CodeGen/AArch64/tail-call.ll | 14 +- test/CodeGen/AArch64/tls-dynamic-together.ll | 2 +- test/CodeGen/AArch64/tls-dynamics.ll | 46 +- test/CodeGen/AArch64/tls-execs.ll | 12 +- test/CodeGen/AArch64/tst-br.ll | 2 +- test/CodeGen/AArch64/variadic.ll | 78 +- test/CodeGen/AArch64/zero-reg.ll | 6 +- test/CodeGen/ARM/2007-01-19-InfiniteLoop.ll | 2 +- test/CodeGen/ARM/2009-08-31-TwoRegShuffle.ll | 2 +- test/CodeGen/ARM/2009-09-28-LdStOptiBug.ll | 2 +- test/CodeGen/ARM/2009-10-16-Scope.ll | 12 +- test/CodeGen/ARM/2009-11-07-SubRegAsmPrinting.ll | 2 +- test/CodeGen/ARM/2010-04-15-ScavengerDebugValue.ll | 22 +- test/CodeGen/ARM/2010-05-18-PostIndexBug.ll | 4 +- .../ARM/2010-06-25-Thumb2ITInvalidIterator.ll | 19 +- test/CodeGen/ARM/2010-08-04-StackVariable.ll | 50 +- test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll | 290 +- test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll | 48 - test/CodeGen/ARM/2010-11-29-PrologueBug.ll | 4 +- test/CodeGen/ARM/2010-11-30-reloc-movt.ll | 27 - test/CodeGen/ARM/2010-12-07-PEIBug.ll | 2 +- test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll | 29 +- test/CodeGen/ARM/2011-03-15-LdStMultipleBug.ll | 13 +- test/CodeGen/ARM/2011-03-23-PeepholeBug.ll | 2 +- test/CodeGen/ARM/2011-04-07-schediv.ll | 2 +- test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll | 9 +- test/CodeGen/ARM/2011-04-26-SchedTweak.ll | 2 +- test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll | 27 +- test/CodeGen/ARM/2011-08-25-ldmia_ret.ll | 2 +- test/CodeGen/ARM/2011-10-26-memset-inline.ll | 4 +- test/CodeGen/ARM/2011-10-26-memset-with-neon.ll | 4 +- .../ARM/2011-11-07-PromoteVectorLoadStore.ll | 4 +- test/CodeGen/ARM/2011-11-09-BitcastVectorDouble.ll | 2 +- test/CodeGen/ARM/2011-11-28-DAGCombineBug.ll | 2 +- test/CodeGen/ARM/2011-11-29-128bitArithmetics.ll | 22 +- test/CodeGen/ARM/2012-03-26-FoldImmBug.ll | 2 +- test/CodeGen/ARM/2012-05-04-vmov.ll | 5 +- test/CodeGen/ARM/2012-08-09-neon-extload.ll | 12 +- test/CodeGen/ARM/2012-08-23-legalize-vmull.ll | 18 +- test/CodeGen/ARM/2012-08-30-select.ll | 11 +- test/CodeGen/ARM/2012-09-18-ARMv4ISelBug.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll | 2 +- test/CodeGen/ARM/2012-10-04-AAPCS-byval-align8.ll | 21 +- test/CodeGen/ARM/2012-10-04-FixedFrame-vs-byval.ll | 2 +- test/CodeGen/ARM/2012-10-04-LDRB_POST_IMM-Crash.ll | 2 +- .../ARM/2012-10-18-PR14099-ByvalFrameAddress.ll | 4 +- test/CodeGen/ARM/2012-11-14-subs_carry.ll | 2 +- test/CodeGen/ARM/2013-01-21-PR14992.ll | 4 +- test/CodeGen/ARM/2013-02-27-expand-vfma.ll | 6 +- .../ARM/2013-04-05-Small-ByVal-Structs-PR15293.ll | 24 +- test/CodeGen/ARM/2013-04-16-AAPCS-C4-vs-VFP.ll | 4 +- test/CodeGen/ARM/2013-04-21-AAPCS-VA-C.1.cp.ll | 2 +- test/CodeGen/ARM/2013-05-05-IfConvertBug.ll | 88 +- test/CodeGen/ARM/2013-05-07-ByteLoadSameAddress.ll | 64 + test/CodeGen/ARM/2013-05-13-AAPCS-byval-padding.ll | 31 + .../CodeGen/ARM/2013-05-13-AAPCS-byval-padding2.ll | 25 + .../ARM/2013-05-13-DAGCombiner-undef-mask.ll | 10 + test/CodeGen/ARM/2013-05-31-char-shift-crash.ll | 21 + test/CodeGen/ARM/2013-06-03-ByVal-2Kbytes.ll | 30 + test/CodeGen/ARM/2013-07-29-vector-or-combine.ll | 32 + test/CodeGen/ARM/2013-10-11-select-stalls.ll | 16 + .../ARM/2013-11-08-inline-asm-neon-array.ll | 16 + test/CodeGen/ARM/a15-SD-dep.ll | 24 +- test/CodeGen/ARM/a15-mla.ll | 26 +- test/CodeGen/ARM/a15-partial-update.ll | 4 +- test/CodeGen/ARM/addrspacecast.ll | 7 + test/CodeGen/ARM/aliases.ll | 27 +- test/CodeGen/ARM/alloc-no-stack-realign.ll | 50 +- test/CodeGen/ARM/arguments.ll | 12 +- test/CodeGen/ARM/arm-and-tst-peephole.ll | 23 + test/CodeGen/ARM/arm-frameaddr.ll | 4 +- test/CodeGen/ARM/arm-modifier.ll | 8 +- test/CodeGen/ARM/arm-returnaddr.ll | 4 +- test/CodeGen/ARM/atomic-64bit.ll | 170 +- test/CodeGen/ARM/atomic-cmp.ll | 4 +- test/CodeGen/ARM/atomic-load-store.ll | 29 +- test/CodeGen/ARM/atomic-op.ll | 25 + test/CodeGen/ARM/atomic-ops-v8.ll | 1344 + test/CodeGen/ARM/atomicrmw_minmax.ll | 4 +- test/CodeGen/ARM/avoid-cpsr-rmw.ll | 6 +- test/CodeGen/ARM/bfc.ll | 6 +- test/CodeGen/ARM/bfi.ll | 4 +- test/CodeGen/ARM/bswap-inline-asm.ll | 2 +- test/CodeGen/ARM/build-attributes-encoding.s | 85 + test/CodeGen/ARM/byval_load_align.ll | 27 + test/CodeGen/ARM/call-noret-minsize.ll | 8 +- test/CodeGen/ARM/call-noret.ll | 8 +- test/CodeGen/ARM/call-tc.ll | 47 +- test/CodeGen/ARM/call_nolink.ll | 4 +- test/CodeGen/ARM/carry.ll | 10 +- test/CodeGen/ARM/coalesce-dbgvalue.ll | 111 + test/CodeGen/ARM/code-placement.ll | 4 +- test/CodeGen/ARM/constantfp.ll | 68 + test/CodeGen/ARM/copy-paired-reg.ll | 17 + test/CodeGen/ARM/crash-greedy-v6.ll | 20 + test/CodeGen/ARM/crash-shufflevector.ll | 2 +- test/CodeGen/ARM/ctz.ll | 2 +- test/CodeGen/ARM/dagcombine-anyexttozeroext.ll | 2 +- test/CodeGen/ARM/dagcombine-concatvector.ll | 4 +- test/CodeGen/ARM/darwin-eabi.ll | 24 + test/CodeGen/ARM/data-in-code-annotations.ll | 4 +- test/CodeGen/ARM/debug-info-arg.ll | 12 +- test/CodeGen/ARM/debug-info-blocks.ll | 68 +- test/CodeGen/ARM/debug-info-branch-folding.ll | 21 +- test/CodeGen/ARM/debug-info-d16-reg.ll | 35 +- test/CodeGen/ARM/debug-info-qreg.ll | 34 +- test/CodeGen/ARM/debug-info-s16-reg.ll | 33 +- test/CodeGen/ARM/debug-info-sreg2.ll | 17 +- test/CodeGen/ARM/div.ll | 23 +- test/CodeGen/ARM/divmod-eabi.ll | 202 + test/CodeGen/ARM/divmod.ll | 20 +- test/CodeGen/ARM/domain-conv-vmovs.ll | 14 +- test/CodeGen/ARM/eh-dispcont.ll | 8 +- test/CodeGen/ARM/ehabi-filters.ll | 2 +- test/CodeGen/ARM/ehabi-mc-cantunwind.ll | 14 - test/CodeGen/ARM/ehabi-mc-compact-pr0.ll | 49 - test/CodeGen/ARM/ehabi-mc-compact-pr1.ll | 62 - test/CodeGen/ARM/ehabi-mc-section-group.ll | 88 - test/CodeGen/ARM/ehabi-mc-section.ll | 71 - test/CodeGen/ARM/ehabi-mc-sh_link.ll | 58 - test/CodeGen/ARM/ehabi-mc.ll | 71 - test/CodeGen/ARM/ehabi.ll | 298 + test/CodeGen/ARM/emit-big-cst.ll | 18 + test/CodeGen/ARM/extload-knownzero.ll | 2 +- test/CodeGen/ARM/fabs-neon.ll | 4 +- test/CodeGen/ARM/fabss.ll | 10 +- test/CodeGen/ARM/fadds.ll | 12 +- test/CodeGen/ARM/fast-isel-GEP-coalesce.ll | 5 +- test/CodeGen/ARM/fast-isel-align.ll | 144 + test/CodeGen/ARM/fast-isel-binary.ll | 5 +- test/CodeGen/ARM/fast-isel-br-const.ll | 17 +- test/CodeGen/ARM/fast-isel-br-phi.ll | 2 +- .../CodeGen/ARM/fast-isel-call-multi-reg-return.ll | 5 +- test/CodeGen/ARM/fast-isel-call.ll | 178 +- test/CodeGen/ARM/fast-isel-cmp-imm.ll | 5 +- test/CodeGen/ARM/fast-isel-conversion.ll | 13 +- test/CodeGen/ARM/fast-isel-crash.ll | 3 +- test/CodeGen/ARM/fast-isel-crash2.ll | 3 +- test/CodeGen/ARM/fast-isel-deadcode.ll | 2 +- test/CodeGen/ARM/fast-isel-ext.ll | 137 + test/CodeGen/ARM/fast-isel-fold.ll | 5 + test/CodeGen/ARM/fast-isel-frameaddr.ll | 30 +- test/CodeGen/ARM/fast-isel-icmp.ll | 13 +- test/CodeGen/ARM/fast-isel-indirectbr.ll | 1 + test/CodeGen/ARM/fast-isel-intrinsic.ll | 100 +- test/CodeGen/ARM/fast-isel-ldr-str-arm.ll | 2 +- .../ARM/fast-isel-ldr-str-thumb-neg-index.ll | 43 +- test/CodeGen/ARM/fast-isel-ldrh-strh-arm.ll | 3 +- test/CodeGen/ARM/fast-isel-load-store-verify.ll | 70 + test/CodeGen/ARM/fast-isel-mvn.ll | 5 +- test/CodeGen/ARM/fast-isel-pic.ll | 26 +- test/CodeGen/ARM/fast-isel-pred.ll | 1 + test/CodeGen/ARM/fast-isel-redefinition.ll | 2 +- test/CodeGen/ARM/fast-isel-ret.ll | 7 +- test/CodeGen/ARM/fast-isel-select.ll | 17 +- test/CodeGen/ARM/fast-isel-shifter.ll | 3 +- test/CodeGen/ARM/fast-isel-static.ll | 8 +- test/CodeGen/ARM/fast-isel-vararg.ll | 47 + test/CodeGen/ARM/fast-isel.ll | 172 +- test/CodeGen/ARM/fast-tail-call.ll | 16 + .../CodeGen/ARM/fastisel-gep-promote-before-add.ll | 18 + test/CodeGen/ARM/fcopysign.ll | 12 +- test/CodeGen/ARM/fdivs.ll | 10 +- test/CodeGen/ARM/fmacs.ll | 30 +- test/CodeGen/ARM/fmscs.ll | 12 +- test/CodeGen/ARM/fmuls.ll | 12 +- test/CodeGen/ARM/fnegs.ll | 24 +- test/CodeGen/ARM/fnmacs.ll | 12 +- test/CodeGen/ARM/fnmscs.ll | 32 +- test/CodeGen/ARM/fold-stack-adjust.ll | 164 + test/CodeGen/ARM/fp.ll | 16 +- test/CodeGen/ARM/fp16.ll | 4 +- test/CodeGen/ARM/fp_convert.ll | 16 +- test/CodeGen/ARM/fparith.ll | 24 +- test/CodeGen/ARM/fpcmp-opt.ll | 11 +- test/CodeGen/ARM/fpcmp.ll | 14 +- test/CodeGen/ARM/fpcmp_ueq.ll | 2 +- test/CodeGen/ARM/fpconsts.ll | 8 +- test/CodeGen/ARM/fpconv.ll | 40 +- test/CodeGen/ARM/fpmem.ll | 10 +- test/CodeGen/ARM/fptoint.ll | 2 +- test/CodeGen/ARM/fusedMAC.ll | 24 +- test/CodeGen/ARM/globals.ll | 2 +- test/CodeGen/ARM/hidden-vis-2.ll | 2 +- test/CodeGen/ARM/hidden-vis.ll | 8 +- test/CodeGen/ARM/ifconv-kills.ll | 30 + test/CodeGen/ARM/ifconv-regmask.ll | 35 + test/CodeGen/ARM/ifcvt1.ll | 4 +- test/CodeGen/ARM/ifcvt10.ll | 2 +- test/CodeGen/ARM/ifcvt11.ll | 2 +- test/CodeGen/ARM/ifcvt12.ll | 2 +- test/CodeGen/ARM/ifcvt2.ll | 4 +- test/CodeGen/ARM/ifcvt3.ll | 2 +- test/CodeGen/ARM/ifcvt4.ll | 2 +- test/CodeGen/ARM/ifcvt5.ll | 4 +- test/CodeGen/ARM/indirect-reg-input.ll | 2 +- test/CodeGen/ARM/indirectbr-2.ll | 2 +- test/CodeGen/ARM/indirectbr-3.ll | 32 + test/CodeGen/ARM/indirectbr.ll | 16 +- test/CodeGen/ARM/inlineasm-64bit.ll | 64 +- test/CodeGen/ARM/inlineasm4.ll | 4 +- test/CodeGen/ARM/interrupt-attr.ll | 130 + test/CodeGen/ARM/intrinsics-crypto.ll | 57 + test/CodeGen/ARM/intrinsics-v8.ll | 19 + test/CodeGen/ARM/ldm.ll | 12 +- test/CodeGen/ARM/ldr.ll | 14 +- test/CodeGen/ARM/ldr_post.ll | 4 +- test/CodeGen/ARM/ldr_pre.ll | 4 +- test/CodeGen/ARM/ldrd.ll | 32 +- test/CodeGen/ARM/ldst-f32-2-i32.ll | 2 +- test/CodeGen/ARM/ldstrex.ll | 139 + test/CodeGen/ARM/ldstrexd.ll | 33 - test/CodeGen/ARM/lit.local.cfg | 2 - test/CodeGen/ARM/load-address-masked.ll | 14 + test/CodeGen/ARM/load-global.ll | 2 +- test/CodeGen/ARM/load_i1_select.ll | 2 +- test/CodeGen/ARM/long.ll | 22 +- test/CodeGen/ARM/longMAC.ll | 8 +- test/CodeGen/ARM/long_shift.ll | 8 +- test/CodeGen/ARM/lsr-icmp-imm.ll | 2 +- test/CodeGen/ARM/lsr-unfolded-offset.ll | 3 +- test/CodeGen/ARM/machine-cse-cmp.ll | 6 +- test/CodeGen/ARM/machine-licm.ll | 8 +- test/CodeGen/ARM/memcpy-inline.ll | 14 +- test/CodeGen/ARM/memset-inline.ll | 4 +- test/CodeGen/ARM/misched-copy-arm.ll | 51 +- test/CodeGen/ARM/mls.ll | 8 +- test/CodeGen/ARM/movt.ll | 4 +- test/CodeGen/ARM/mul_const.ll | 20 +- test/CodeGen/ARM/mulhi.ll | 18 +- test/CodeGen/ARM/mvn.ll | 2 +- test/CodeGen/ARM/neon-spfp.ll | 60 +- test/CodeGen/ARM/neon_minmax.ll | 20 +- test/CodeGen/ARM/neon_spill.ll | 11 +- test/CodeGen/ARM/neon_vabs.ll | 20 +- test/CodeGen/ARM/no-fpu.ll | 33 + test/CodeGen/ARM/noreturn.ll | 50 + test/CodeGen/ARM/optselect-regclass.ll | 23 + test/CodeGen/ARM/pack.ll | 25 +- test/CodeGen/ARM/peephole-bitcast.ll | 2 +- test/CodeGen/ARM/pic.ll | 23 + test/CodeGen/ARM/popcnt.ll | 36 +- test/CodeGen/ARM/prefetch-thumb.ll | 22 + test/CodeGen/ARM/prefetch.ll | 22 +- test/CodeGen/ARM/private.ll | 2 +- test/CodeGen/ARM/readcyclecounter.ll | 24 + test/CodeGen/ARM/reg_sequence.ll | 25 +- test/CodeGen/ARM/ret_sret_vector.ll | 2 +- test/CodeGen/ARM/returned-ext.ll | 28 +- test/CodeGen/ARM/returned-trunc-tail-calls.ll | 111 + test/CodeGen/ARM/rev.ll | 4 +- test/CodeGen/ARM/sbfx.ll | 10 +- test/CodeGen/ARM/section-name.ll | 25 + test/CodeGen/ARM/select-imm.ll | 68 +- test/CodeGen/ARM/select-undef.ll | 7 + test/CodeGen/ARM/select.ll | 28 +- test/CodeGen/ARM/select_xform.ll | 48 +- test/CodeGen/ARM/setcc-sentinals.ll | 14 + test/CodeGen/ARM/shifter_operand.ll | 16 +- test/CodeGen/ARM/sincos.ll | 38 + test/CodeGen/ARM/spill-q.ll | 2 +- test/CodeGen/ARM/stack-protector-bmovpcb_call.ll | 32 + test/CodeGen/ARM/str_post.ll | 4 +- test/CodeGen/ARM/struct-byval-frame-index.ll | 219 + test/CodeGen/ARM/struct_byval.ll | 53 +- test/CodeGen/ARM/struct_byval_arm_t1_t2.ll | 1523 ++ test/CodeGen/ARM/sub-cmp-peephole.ll | 70 +- test/CodeGen/ARM/swift-atomics.ll | 45 + test/CodeGen/ARM/swift-vldm.ll | 29 + test/CodeGen/ARM/tail-dup.ll | 2 +- test/CodeGen/ARM/tail-opts.ll | 2 +- test/CodeGen/ARM/test-sharedidx.ll | 2 +- test/CodeGen/ARM/this-return.ll | 24 +- test/CodeGen/ARM/thumb1-varalloc.ll | 2 +- test/CodeGen/ARM/thumb2-it-block.ll | 5 +- test/CodeGen/ARM/tls-models.ll | 32 +- test/CodeGen/ARM/tls2.ll | 8 +- test/CodeGen/ARM/trap.ll | 12 +- test/CodeGen/ARM/twoaddrinstr.ll | 2 +- test/CodeGen/ARM/umulo-32.ll | 8 +- test/CodeGen/ARM/unaligned_load_store.ll | 16 +- test/CodeGen/ARM/unaligned_load_store_vector.ll | 54 +- test/CodeGen/ARM/undef-sext.ll | 2 +- test/CodeGen/ARM/unwind-init.ll | 18 + test/CodeGen/ARM/v1-constant-fold.ll | 2 +- test/CodeGen/ARM/va_arg.ll | 4 +- test/CodeGen/ARM/vaba.ll | 36 +- test/CodeGen/ARM/vabd.ll | 40 +- test/CodeGen/ARM/vabs.ll | 28 +- test/CodeGen/ARM/vadd.ll | 108 +- test/CodeGen/ARM/vbits.ll | 114 +- test/CodeGen/ARM/vbsl-constant.ll | 16 +- test/CodeGen/ARM/vbsl.ll | 40 +- test/CodeGen/ARM/vceq.ll | 18 +- test/CodeGen/ARM/vcge.ll | 38 +- test/CodeGen/ARM/vcgt.ll | 38 +- test/CodeGen/ARM/vcnt.ll | 28 +- test/CodeGen/ARM/vcvt-cost.ll | 20 +- test/CodeGen/ARM/vcvt-v8.ll | 145 + test/CodeGen/ARM/vcvt.ll | 77 +- test/CodeGen/ARM/vdiv_combine.ll | 41 + test/CodeGen/ARM/vdup.ll | 64 +- test/CodeGen/ARM/vector-DAGCombine.ll | 90 +- test/CodeGen/ARM/vector-extend-narrow.ll | 10 +- test/CodeGen/ARM/vext.ll | 59 +- test/CodeGen/ARM/vfcmp.ll | 22 +- test/CodeGen/ARM/vfp.ll | 24 +- test/CodeGen/ARM/vget_lane.ll | 34 +- test/CodeGen/ARM/vhadd.ll | 48 +- test/CodeGen/ARM/vhsub.ll | 24 +- test/CodeGen/ARM/vicmp.ll | 20 +- test/CodeGen/ARM/vld1.ll | 26 +- test/CodeGen/ARM/vld2.ll | 22 +- test/CodeGen/ARM/vld3.ll | 22 +- test/CodeGen/ARM/vld4.ll | 22 +- test/CodeGen/ARM/vlddup.ll | 28 +- test/CodeGen/ARM/vldlane.ll | 68 +- test/CodeGen/ARM/vldm-liveness.ll | 40 + test/CodeGen/ARM/vldm-sched-a9.ll | 71 + test/CodeGen/ARM/vminmax.ll | 56 +- test/CodeGen/ARM/vminmaxnm.ll | 88 + test/CodeGen/ARM/vmla.ll | 28 +- test/CodeGen/ARM/vmls.ll | 28 +- test/CodeGen/ARM/vmov.ll | 104 +- test/CodeGen/ARM/vmul.ll | 89 +- test/CodeGen/ARM/vneg.ll | 28 +- test/CodeGen/ARM/vpadal.ll | 24 +- test/CodeGen/ARM/vpadd.ll | 32 +- test/CodeGen/ARM/vpminmax.ll | 28 +- test/CodeGen/ARM/vqadd.ll | 32 +- test/CodeGen/ARM/vqdmul.ll | 124 +- test/CodeGen/ARM/vqshl.ll | 112 +- test/CodeGen/ARM/vqshrn.ll | 36 +- test/CodeGen/ARM/vqsub.ll | 32 +- test/CodeGen/ARM/vrec.ll | 24 +- test/CodeGen/ARM/vrev.ll | 36 +- test/CodeGen/ARM/vsel.ll | 309 + test/CodeGen/ARM/vselect_imax.ll | 58 +- test/CodeGen/ARM/vshift.ll | 96 +- test/CodeGen/ARM/vshiftins.ll | 32 +- test/CodeGen/ARM/vshl.ll | 144 +- test/CodeGen/ARM/vshll.ll | 18 +- test/CodeGen/ARM/vshrn.ll | 12 +- test/CodeGen/ARM/vsra.ll | 64 +- test/CodeGen/ARM/vst1.ll | 24 +- test/CodeGen/ARM/vst2.ll | 26 +- test/CodeGen/ARM/vst3.ll | 22 +- test/CodeGen/ARM/vst4.ll | 22 +- test/CodeGen/ARM/vstlane.ll | 72 +- test/CodeGen/ARM/vsub.ll | 96 +- test/CodeGen/ARM/vtbl.ll | 16 +- test/CodeGen/ARM/vtrn.ll | 20 +- test/CodeGen/ARM/vuzp.ll | 16 +- test/CodeGen/ARM/vzip.ll | 16 +- test/CodeGen/ARM/warn-stack.ll | 24 + test/CodeGen/CPP/lit.local.cfg | 2 - test/CodeGen/Generic/2009-03-17-LSR-APInt.ll | 56 +- test/CodeGen/Generic/crash.ll | 4 +- test/CodeGen/Generic/dbg_value.ll | 3 +- test/CodeGen/Generic/lit.local.cfg | 1 - test/CodeGen/Hexagon/BranchPredict.ll | 76 + test/CodeGen/Hexagon/adde.ll | 2 +- test/CodeGen/Hexagon/args.ll | 9 +- test/CodeGen/Hexagon/combine_ir.ll | 15 +- test/CodeGen/Hexagon/extload-combine.ll | 80 + test/CodeGen/Hexagon/hwloop-dbg.ll | 27 +- test/CodeGen/Hexagon/i16_VarArg.ll | 2 +- test/CodeGen/Hexagon/i1_VarArg.ll | 2 +- test/CodeGen/Hexagon/i8_VarArg.ll | 2 +- test/CodeGen/Hexagon/indirect-br.ll | 2 +- test/CodeGen/Hexagon/lit.local.cfg | 2 - test/CodeGen/Hexagon/memops.ll | 509 +- test/CodeGen/Hexagon/packetize_cond_inst.ll | 32 + test/CodeGen/Hexagon/pred-gp.ll | 28 + test/CodeGen/Hexagon/pred-instrs.ll | 30 + test/CodeGen/Hexagon/split-const32-const64.ll | 26 + test/CodeGen/Hexagon/sube.ll | 2 +- test/CodeGen/Hexagon/tail-call-trunc.ll | 28 + test/CodeGen/Hexagon/tfr-to-combine.ll | 35 + test/CodeGen/Hexagon/union-1.ll | 8 +- test/CodeGen/Hexagon/zextloadi1.ll | 2 +- test/CodeGen/Inputs/DbgValueOtherTargets.ll | 12 +- test/CodeGen/MBlaze/DbgValueOtherTargets.test | 1 - test/CodeGen/MBlaze/brind.ll | 72 - test/CodeGen/MBlaze/callind.ll | 80 - test/CodeGen/MBlaze/cc.ll | 266 - test/CodeGen/MBlaze/div.ll | 75 - test/CodeGen/MBlaze/fpu.ll | 66 - test/CodeGen/MBlaze/fsl.ll | 319 - test/CodeGen/MBlaze/imm.ll | 70 - test/CodeGen/MBlaze/intr.ll | 48 - test/CodeGen/MBlaze/jumptable.ll | 79 - test/CodeGen/MBlaze/lit.local.cfg | 6 - test/CodeGen/MBlaze/loop.ll | 44 - test/CodeGen/MBlaze/mul.ll | 51 - test/CodeGen/MBlaze/mul64.ll | 23 - test/CodeGen/MBlaze/select.ll | 15 - test/CodeGen/MBlaze/shift.ll | 115 - test/CodeGen/MBlaze/svol.ll | 80 - test/CodeGen/MSP430/2009-11-05-8BitLibcalls.ll | 2 +- test/CodeGen/MSP430/AddrMode-bis-rx.ll | 14 +- test/CodeGen/MSP430/AddrMode-bis-xr.ll | 14 +- test/CodeGen/MSP430/AddrMode-mov-rx.ll | 14 +- test/CodeGen/MSP430/AddrMode-mov-xr.ll | 14 +- test/CodeGen/MSP430/Inst16mi.ll | 10 +- test/CodeGen/MSP430/Inst16mm.ll | 12 +- test/CodeGen/MSP430/Inst16mr.ll | 12 +- test/CodeGen/MSP430/Inst16ri.ll | 10 +- test/CodeGen/MSP430/Inst16rm.ll | 10 +- test/CodeGen/MSP430/Inst16rr.ll | 12 +- test/CodeGen/MSP430/Inst8mi.ll | 10 +- test/CodeGen/MSP430/Inst8mm.ll | 10 +- test/CodeGen/MSP430/Inst8mr.ll | 12 +- test/CodeGen/MSP430/Inst8ri.ll | 10 +- test/CodeGen/MSP430/Inst8rm.ll | 10 +- test/CodeGen/MSP430/Inst8rr.ll | 12 +- test/CodeGen/MSP430/bit.ll | 32 +- test/CodeGen/MSP430/byval.ll | 4 +- test/CodeGen/MSP430/cc_args.ll | 118 + test/CodeGen/MSP430/cc_ret.ll | 61 + test/CodeGen/MSP430/fp.ll | 2 +- test/CodeGen/MSP430/indirectbr2.ll | 2 +- test/CodeGen/MSP430/jumptable.ll | 54 + test/CodeGen/MSP430/lit.local.cfg | 2 - test/CodeGen/MSP430/postinc.ll | 10 +- test/CodeGen/MSP430/setcc.ll | 34 +- test/CodeGen/MSP430/shifts.ll | 10 +- test/CodeGen/MSP430/transient-stack-alignment.ll | 17 + test/CodeGen/MSP430/vararg.ll | 6 +- test/CodeGen/Mips/2008-07-16-SignExtInReg.ll | 1 + test/CodeGen/Mips/2008-08-01-AsmInline.ll | 18 + test/CodeGen/Mips/2013-11-18-fp64-const0.ll | 31 + test/CodeGen/Mips/align16.ll | 8 +- test/CodeGen/Mips/alloca16.ll | 4 +- test/CodeGen/Mips/atomic.ll | 495 +- test/CodeGen/Mips/atomicops.ll | 4 +- test/CodeGen/Mips/beqzc.ll | 20 + test/CodeGen/Mips/beqzc1.ll | 24 + test/CodeGen/Mips/biggot.ll | 4 +- test/CodeGen/Mips/blez_bgez.ll | 36 + test/CodeGen/Mips/blockaddr.ll | 10 + test/CodeGen/Mips/brdelayslot.ll | 31 +- test/CodeGen/Mips/brsize3.ll | 33 + test/CodeGen/Mips/brsize3a.ll | 26 + test/CodeGen/Mips/bswap.ll | 7 +- test/CodeGen/Mips/buildpairextractelementf64.ll | 23 +- test/CodeGen/Mips/check-noat.ll | 2 +- test/CodeGen/Mips/cmov.ll | 44 +- test/CodeGen/Mips/cmplarge.ll | 38 + test/CodeGen/Mips/const-mult.ll | 49 + test/CodeGen/Mips/const1.ll | 35 + test/CodeGen/Mips/const4a.ll | 180 + test/CodeGen/Mips/const6.ll | 164 + test/CodeGen/Mips/const6a.ll | 29 + test/CodeGen/Mips/ctlz.ll | 27 + test/CodeGen/Mips/disable-tail-merge.ll | 33 + test/CodeGen/Mips/divrem.ll | 48 +- test/CodeGen/Mips/dsp-patterns-cmp-vselect.ll | 80 +- test/CodeGen/Mips/dsp-patterns.ll | 46 +- test/CodeGen/Mips/dsp-vec-load-store.ll | 11 + test/CodeGen/Mips/eh-return64.ll | 12 +- test/CodeGen/Mips/emit-big-cst.ll | 17 + test/CodeGen/Mips/ex2.ll | 11 +- test/CodeGen/Mips/extins.ll | 9 +- test/CodeGen/Mips/f16abs.ll | 37 + test/CodeGen/Mips/fcopysign-f32-f64.ll | 35 +- test/CodeGen/Mips/fixdfsf.ll | 18 + test/CodeGen/Mips/fp16instrinsmc.ll | 391 + test/CodeGen/Mips/fp16mix.ll | 92 + test/CodeGen/Mips/fpneeded.ll | 2 +- test/CodeGen/Mips/fpnotneeded.ll | 2 +- test/CodeGen/Mips/fptr2.ll | 20 + test/CodeGen/Mips/frame-address.ll | 7 +- test/CodeGen/Mips/helloworld.ll | 26 +- test/CodeGen/Mips/hf16call32.ll | 1030 + test/CodeGen/Mips/hf16call32_body.ll | 294 + test/CodeGen/Mips/hf1_body.ll | 21 + test/CodeGen/Mips/hfptrcall.ll | 125 + test/CodeGen/Mips/i32k.ll | 19 +- test/CodeGen/Mips/i64arg.ll | 32 +- test/CodeGen/Mips/inlineasm-operand-code.ll | 24 +- test/CodeGen/Mips/int-to-float-conversion.ll | 48 + test/CodeGen/Mips/largefr1.ll | 41 +- test/CodeGen/Mips/largeimmprinting.ll | 4 +- test/CodeGen/Mips/lazy-binding.ll | 41 + test/CodeGen/Mips/lit.local.cfg | 2 - test/CodeGen/Mips/longbranch.ll | 8 +- test/CodeGen/Mips/mips16_32_1.ll | 2 +- test/CodeGen/Mips/mips16_32_10.ll | 6 +- test/CodeGen/Mips/mips16_32_3.ll | 6 +- test/CodeGen/Mips/mips16_32_4.ll | 6 +- test/CodeGen/Mips/mips16_32_5.ll | 6 +- test/CodeGen/Mips/mips16_32_6.ll | 6 +- test/CodeGen/Mips/mips16_32_7.ll | 6 +- test/CodeGen/Mips/mips16_32_8.ll | 8 +- test/CodeGen/Mips/mips16_32_9.ll | 6 +- test/CodeGen/Mips/mips16_fpret.ll | 76 + test/CodeGen/Mips/mips16fpe.ll | 56 +- test/CodeGen/Mips/mips64-f128.ll | 146 +- test/CodeGen/Mips/mips64-libcall.ll | 4 +- test/CodeGen/Mips/mips64instrs.ll | 32 +- test/CodeGen/Mips/misha.ll | 4 +- test/CodeGen/Mips/mno-ldc1-sdc1.ll | 93 + test/CodeGen/Mips/msa/2r.ll | 257 + test/CodeGen/Mips/msa/2r_vector_scalar.ll | 87 + test/CodeGen/Mips/msa/2rf.ll | 323 + test/CodeGen/Mips/msa/2rf_exup.ll | 82 + test/CodeGen/Mips/msa/2rf_float_int.ll | 90 + test/CodeGen/Mips/msa/2rf_fq.ll | 82 + test/CodeGen/Mips/msa/2rf_int_float.ll | 217 + test/CodeGen/Mips/msa/2rf_tq.ll | 50 + test/CodeGen/Mips/msa/3r-a.ll | 1191 + test/CodeGen/Mips/msa/3r-b.ll | 494 + test/CodeGen/Mips/msa/3r-c.ll | 446 + test/CodeGen/Mips/msa/3r-d.ll | 478 + test/CodeGen/Mips/msa/3r-i.ll | 358 + test/CodeGen/Mips/msa/3r-m.ll | 862 + test/CodeGen/Mips/msa/3r-p.ll | 182 + test/CodeGen/Mips/msa/3r-s.ll | 1353 + test/CodeGen/Mips/msa/3r-v.ll | 105 + test/CodeGen/Mips/msa/3r_4r.ll | 206 + test/CodeGen/Mips/msa/3r_4r_widen.ll | 307 + test/CodeGen/Mips/msa/3r_splat.ll | 94 + test/CodeGen/Mips/msa/3rf.ll | 485 + test/CodeGen/Mips/msa/3rf_4rf.ll | 106 + test/CodeGen/Mips/msa/3rf_4rf_q.ll | 206 + test/CodeGen/Mips/msa/3rf_exdo.ll | 50 + test/CodeGen/Mips/msa/3rf_float_int.ll | 50 + test/CodeGen/Mips/msa/3rf_int_float.ll | 974 + test/CodeGen/Mips/msa/3rf_q.ll | 94 + test/CodeGen/Mips/msa/arithmetic.ll | 726 + test/CodeGen/Mips/msa/arithmetic_float.ll | 456 + test/CodeGen/Mips/msa/basic_operations.ll | 481 + test/CodeGen/Mips/msa/basic_operations_float.ll | 207 + test/CodeGen/Mips/msa/bit.ll | 537 + test/CodeGen/Mips/msa/bitcast.ll | 1210 + test/CodeGen/Mips/msa/bitwise.ll | 1639 ++ test/CodeGen/Mips/msa/compare.ll | 2079 ++ test/CodeGen/Mips/msa/compare_float.ll | 663 + test/CodeGen/Mips/msa/elm_copy.ll | 162 + test/CodeGen/Mips/msa/elm_cxcmsa.ll | 168 + test/CodeGen/Mips/msa/elm_insv.ll | 192 + test/CodeGen/Mips/msa/elm_move.ll | 25 + test/CodeGen/Mips/msa/elm_shift_slide.ll | 158 + test/CodeGen/Mips/msa/endian.ll | 107 + test/CodeGen/Mips/msa/frameindex.ll | 85 + test/CodeGen/Mips/msa/i10.ll | 89 + test/CodeGen/Mips/msa/i5-a.ll | 82 + test/CodeGen/Mips/msa/i5-b.ll | 439 + test/CodeGen/Mips/msa/i5-c.ll | 386 + test/CodeGen/Mips/msa/i5-m.ll | 310 + test/CodeGen/Mips/msa/i5-s.ll | 82 + test/CodeGen/Mips/msa/i5_ld_st.ll | 150 + test/CodeGen/Mips/msa/i8.ll | 211 + test/CodeGen/Mips/msa/inline-asm.ll | 34 + test/CodeGen/Mips/msa/llvm-stress-s1704963983.ll | 134 + test/CodeGen/Mips/msa/llvm-stress-s1935737938.ll | 138 + .../Mips/msa/llvm-stress-s2090927243-simplified.ll | 31 + .../Mips/msa/llvm-stress-s2501752154-simplified.ll | 27 + test/CodeGen/Mips/msa/llvm-stress-s2704903805.ll | 141 + test/CodeGen/Mips/msa/llvm-stress-s3861334421.ll | 149 + test/CodeGen/Mips/msa/llvm-stress-s3926023935.ll | 143 + test/CodeGen/Mips/msa/llvm-stress-s3997499501.ll | 152 + .../Mips/msa/llvm-stress-s449609655-simplified.ll | 33 + test/CodeGen/Mips/msa/llvm-stress-s525530439.ll | 139 + test/CodeGen/Mips/msa/llvm-stress-s997348632.ll | 143 + .../CodeGen/Mips/msa/llvm-stress-sz1-s742806235.ll | 23 + test/CodeGen/Mips/msa/shift-dagcombine.ll | 70 + test/CodeGen/Mips/msa/shuffle.ll | 803 + test/CodeGen/Mips/msa/special.ll | 26 + test/CodeGen/Mips/msa/spill.ll | 601 + test/CodeGen/Mips/msa/vec.ll | 946 + test/CodeGen/Mips/msa/vecs10.ll | 47 + test/CodeGen/Mips/nomips16.ll | 38 + test/CodeGen/Mips/o32_cc.ll | 242 +- test/CodeGen/Mips/o32_cc_byval.ll | 62 +- test/CodeGen/Mips/o32_cc_vararg.ll | 20 +- test/CodeGen/Mips/optimize-fp-math.ll | 32 + test/CodeGen/Mips/powif64_16.ll | 26 + test/CodeGen/Mips/private.ll | 4 +- test/CodeGen/Mips/ra-allocatable.ll | 367 +- test/CodeGen/Mips/return-vector.ll | 42 +- test/CodeGen/Mips/rotate.ll | 5 + test/CodeGen/Mips/sel1c.ll | 21 + test/CodeGen/Mips/sel2c.ll | 21 + test/CodeGen/Mips/selectcc.ll | 16 + test/CodeGen/Mips/selnek.ll | 2 +- test/CodeGen/Mips/setcc-se.ll | 155 + test/CodeGen/Mips/simplebr.ll | 37 + test/CodeGen/Mips/sint-fp-store_pattern.ll | 52 + test/CodeGen/Mips/stack-alignment.ll | 13 + test/CodeGen/Mips/stackcoloring.ll | 39 + test/CodeGen/Mips/stchar.ll | 4 +- test/CodeGen/Mips/tailcall.ll | 13 + test/CodeGen/Mips/tls-alias.ll | 4 +- test/CodeGen/Mips/tls-models.ll | 32 +- test/CodeGen/Mips/tls.ll | 34 +- test/CodeGen/Mips/tnaked.ll | 8 +- test/CodeGen/Mips/trap.ll | 11 + test/CodeGen/Mips/trap1.ll | 13 + test/CodeGen/Mips/unalignedload.ll | 20 +- test/CodeGen/NVPTX/add-128bit.ll | 19 + test/CodeGen/NVPTX/bug17709.ll | 26 + test/CodeGen/NVPTX/callchain.ll | 10 + test/CodeGen/NVPTX/compare-int.ll | 60 +- test/CodeGen/NVPTX/constant-vectors.ll | 6 + test/CodeGen/NVPTX/convert-int-sm20.ll | 8 +- test/CodeGen/NVPTX/ctlz.ll | 44 + test/CodeGen/NVPTX/ctpop.ll | 25 + test/CodeGen/NVPTX/cttz.ll | 45 + test/CodeGen/NVPTX/fast-math.ll | 43 + test/CodeGen/NVPTX/fp-literals.ll | 18 + test/CodeGen/NVPTX/generic-to-nvvm.ll | 3 +- test/CodeGen/NVPTX/i1-global.ll | 4 +- test/CodeGen/NVPTX/i1-int-to-fp.ll | 37 + test/CodeGen/NVPTX/i1-param.ll | 3 +- test/CodeGen/NVPTX/i8-param.ll | 23 + test/CodeGen/NVPTX/implicit-def.ll | 9 + test/CodeGen/NVPTX/inline-asm.ll | 9 + test/CodeGen/NVPTX/intrinsic-old.ll | 66 +- test/CodeGen/NVPTX/intrinsics.ll | 4 +- test/CodeGen/NVPTX/ld-addrspace.ll | 24 +- test/CodeGen/NVPTX/ld-generic.ll | 8 +- test/CodeGen/NVPTX/ldu-i8.ll | 14 + test/CodeGen/NVPTX/ldu-reg-plus-offset.ll | 21 + test/CodeGen/NVPTX/lit.local.cfg | 2 - test/CodeGen/NVPTX/load-sext-i1.ll | 14 + test/CodeGen/NVPTX/local-stack-frame.ll | 18 + test/CodeGen/NVPTX/module-inline-asm.ll | 10 + test/CodeGen/NVPTX/pr13291-i1-store.ll | 20 +- test/CodeGen/NVPTX/pr16278.ll | 10 + test/CodeGen/NVPTX/pr17529.ll | 38 + test/CodeGen/NVPTX/refl1.ll | 4 +- test/CodeGen/NVPTX/rsqrt.ll | 13 + test/CodeGen/NVPTX/sext-in-reg.ll | 111 + test/CodeGen/NVPTX/sext-params.ll | 16 + test/CodeGen/NVPTX/st-addrspace.ll | 12 +- test/CodeGen/NVPTX/st-generic.ll | 4 +- test/CodeGen/NVPTX/vec-param-load.ll | 13 + test/CodeGen/NVPTX/vec8.ll | 13 + test/CodeGen/NVPTX/vector-args.ll | 16 +- test/CodeGen/NVPTX/vector-stores.ll | 30 + .../CodeGen/PowerPC/2007-11-16-landingpad-split.ll | 16 +- test/CodeGen/PowerPC/2009-09-18-carrybit.ll | 2 +- test/CodeGen/PowerPC/2010-02-12-saveCR.ll | 2 +- test/CodeGen/PowerPC/2010-12-18-PPCStackRefs.ll | 2 +- .../PowerPC/2011-12-08-DemandedBitsMiscompile.ll | 2 +- test/CodeGen/PowerPC/2013-05-15-preinc-fold.ll | 33 + test/CodeGen/PowerPC/2013-07-01-PHIElimBug.ll | 28 + test/CodeGen/PowerPC/Frames-alloca.ll | 14 +- test/CodeGen/PowerPC/addc.ll | 6 +- test/CodeGen/PowerPC/addrfuncstr.ll | 27 + test/CodeGen/PowerPC/altivec-ord.ll | 17 + test/CodeGen/PowerPC/anon_aggr.ll | 108 +- test/CodeGen/PowerPC/ashr-neg1.ll | 18 + test/CodeGen/PowerPC/asm-dialect.ll | 18 + test/CodeGen/PowerPC/asym-regclass-copy.ll | 2 +- test/CodeGen/PowerPC/atomic-1.ll | 6 +- test/CodeGen/PowerPC/atomic-2.ll | 6 +- test/CodeGen/PowerPC/bdzlr.ll | 11 +- test/CodeGen/PowerPC/bv-pres-v8i1.ll | 39 + test/CodeGen/PowerPC/bv-widen-undef.ll | 23 + test/CodeGen/PowerPC/complex-return.ll | 4 +- test/CodeGen/PowerPC/copysignl.ll | 67 + test/CodeGen/PowerPC/cr-spills.ll | 107 +- test/CodeGen/PowerPC/crsave.ll | 27 +- test/CodeGen/PowerPC/ctr-cleanup.ll | 2 +- test/CodeGen/PowerPC/ctrloop-asm.ll | 38 + test/CodeGen/PowerPC/ctrloop-cpsgn.ll | 28 + test/CodeGen/PowerPC/ctrloop-fp64.ll | 60 + test/CodeGen/PowerPC/ctrloop-i64.ll | 93 + test/CodeGen/PowerPC/ctrloop-large-ec.ll | 23 + test/CodeGen/PowerPC/ctrloop-le.ll | 441 + test/CodeGen/PowerPC/ctrloop-lt.ll | 438 + test/CodeGen/PowerPC/ctrloop-ne.ll | 449 + test/CodeGen/PowerPC/ctrloops.ll | 6 +- test/CodeGen/PowerPC/dbg.ll | 24 +- test/CodeGen/PowerPC/dyn-alloca-aligned.ll | 35 + test/CodeGen/PowerPC/emptystruct.ll | 8 +- test/CodeGen/PowerPC/fast-isel-GEP-coalesce.ll | 48 + test/CodeGen/PowerPC/fast-isel-binary.ll | 137 + test/CodeGen/PowerPC/fast-isel-br-const.ll | 43 + test/CodeGen/PowerPC/fast-isel-call.ll | 132 + test/CodeGen/PowerPC/fast-isel-cmp-imm.ll | 289 + test/CodeGen/PowerPC/fast-isel-conversion.ll | 305 + test/CodeGen/PowerPC/fast-isel-crash.ll | 23 + test/CodeGen/PowerPC/fast-isel-ext.ll | 75 + test/CodeGen/PowerPC/fast-isel-fold.ll | 129 + test/CodeGen/PowerPC/fast-isel-indirectbr.ll | 15 + test/CodeGen/PowerPC/fast-isel-load-store.ll | 202 + test/CodeGen/PowerPC/fast-isel-redefinition.ll | 10 + test/CodeGen/PowerPC/fast-isel-ret.ll | 142 + test/CodeGen/PowerPC/fast-isel-shifter.ll | 50 + .../PowerPC/fastisel-gep-promote-before-add.ll | 17 + test/CodeGen/PowerPC/fcpsgn.ll | 52 + test/CodeGen/PowerPC/floatPSA.ll | 2 +- test/CodeGen/PowerPC/fma.ll | 16 +- test/CodeGen/PowerPC/frameaddr.ll | 4 +- test/CodeGen/PowerPC/glob-comp-aa-crash.ll | 139 + test/CodeGen/PowerPC/hello-reloc.s | 84 + test/CodeGen/PowerPC/i64_fp_round.ll | 2 +- test/CodeGen/PowerPC/indirectbr.ll | 6 +- test/CodeGen/PowerPC/inlineasm-i64-reg.ll | 108 + test/CodeGen/PowerPC/isel-rc-nox0.ll | 46 + test/CodeGen/PowerPC/jaggedstructs.ll | 28 +- test/CodeGen/PowerPC/lit.local.cfg | 2 - test/CodeGen/PowerPC/mcm-1.ll | 2 +- test/CodeGen/PowerPC/mcm-10.ll | 2 +- test/CodeGen/PowerPC/mcm-11.ll | 2 +- test/CodeGen/PowerPC/mcm-12.ll | 2 +- test/CodeGen/PowerPC/mcm-2.ll | 12 +- test/CodeGen/PowerPC/mcm-3.ll | 12 +- test/CodeGen/PowerPC/mcm-4.ll | 12 +- test/CodeGen/PowerPC/mcm-5.ll | 2 +- test/CodeGen/PowerPC/mcm-6.ll | 2 +- test/CodeGen/PowerPC/mcm-7.ll | 2 +- test/CodeGen/PowerPC/mcm-8.ll | 2 +- test/CodeGen/PowerPC/mcm-9.ll | 5 +- test/CodeGen/PowerPC/mcm-default.ll | 2 +- test/CodeGen/PowerPC/mcm-obj-2.ll | 2 +- test/CodeGen/PowerPC/mcm-obj.ll | 8 +- test/CodeGen/PowerPC/misched-inorder-latency.ll | 4 +- test/CodeGen/PowerPC/mulli64.ll | 16 + test/CodeGen/PowerPC/negctr.ll | 9 +- test/CodeGen/PowerPC/optcmp.ll | 39 +- test/CodeGen/PowerPC/ppc32-vacopy.ll | 24 + test/CodeGen/PowerPC/ppc64-align-long-double.ll | 2 +- test/CodeGen/PowerPC/ppc64-calls.ll | 10 +- test/CodeGen/PowerPC/ppc64-toc.ll | 8 +- test/CodeGen/PowerPC/pr13891.ll | 2 +- test/CodeGen/PowerPC/pr15031.ll | 26 +- test/CodeGen/PowerPC/pr16556-2.ll | 41 + test/CodeGen/PowerPC/pr16556.ll | 20 + test/CodeGen/PowerPC/pr16573.ll | 11 + test/CodeGen/PowerPC/pr17168.ll | 521 + test/CodeGen/PowerPC/pr17354.ll | 39 + test/CodeGen/PowerPC/recipest.ll | 37 +- test/CodeGen/PowerPC/reg-names.ll | 17 + test/CodeGen/PowerPC/reloc-align.ll | 34 + test/CodeGen/PowerPC/remap-crash.ll | 57 + test/CodeGen/PowerPC/rlwimi-and.ll | 43 + test/CodeGen/PowerPC/rounding-ops.ll | 91 +- test/CodeGen/PowerPC/rs-undef-use.ll | 48 + test/CodeGen/PowerPC/set0-v8i16.ll | 18 + test/CodeGen/PowerPC/sj-ctr-loop.ll | 50 + test/CodeGen/PowerPC/sjlj.ll | 66 +- test/CodeGen/PowerPC/stack-protector.ll | 5 +- test/CodeGen/PowerPC/stack-realign.ll | 147 + test/CodeGen/PowerPC/std-unal-fi.ll | 119 + test/CodeGen/PowerPC/store-update.ll | 56 +- test/CodeGen/PowerPC/structsinmem.ll | 2 +- test/CodeGen/PowerPC/structsinregs.ll | 2 +- test/CodeGen/PowerPC/sub-bv-types.ll | 17 + test/CodeGen/PowerPC/subsumes-pred-regs.ll | 65 + test/CodeGen/PowerPC/svr4-redzone.ll | 12 +- test/CodeGen/PowerPC/tls-2.ll | 2 +- test/CodeGen/PowerPC/tls-gd-obj.ll | 31 - test/CodeGen/PowerPC/tls-ie-obj.ll | 29 - test/CodeGen/PowerPC/tls-ld-obj.ll | 34 - test/CodeGen/PowerPC/tls.ll | 4 +- test/CodeGen/PowerPC/unal-altivec.ll | 52 + test/CodeGen/PowerPC/unal-altivec2.ll | 166 + test/CodeGen/PowerPC/unal4-std.ll | 2 +- test/CodeGen/PowerPC/unwind-dw2-g.ll | 35 + test/CodeGen/PowerPC/unwind-dw2.ll | 15 + test/CodeGen/PowerPC/vaddsplat.ll | 24 +- test/CodeGen/PowerPC/varargs.ll | 4 +- test/CodeGen/PowerPC/vec-abi-align.ll | 60 + test/CodeGen/PowerPC/vec_cmp.ll | 100 +- test/CodeGen/PowerPC/vec_constants.ll | 16 +- test/CodeGen/PowerPC/vec_conv.ll | 8 +- test/CodeGen/PowerPC/vec_extload.ll | 14 +- test/CodeGen/PowerPC/vec_fmuladd.ll | 56 + test/CodeGen/PowerPC/vec_mul.ll | 8 +- test/CodeGen/PowerPC/vec_rounding.ll | 32 +- test/CodeGen/PowerPC/vec_sqrt.ll | 10 +- test/CodeGen/PowerPC/vector.ll | 8 + test/CodeGen/PowerPC/vrspill.ll | 7 +- test/CodeGen/PowerPC/zero-not-run.ll | 27 + test/CodeGen/R600/128bit-kernel-args.ll | 22 +- test/CodeGen/R600/32-bit-local-address-space.ll | 88 + test/CodeGen/R600/64bit-kernel-args.ll | 11 + test/CodeGen/R600/add.ll | 57 +- test/CodeGen/R600/add_i64.ll | 59 + test/CodeGen/R600/address-space.ll | 31 + test/CodeGen/R600/alu-split.ll | 851 - test/CodeGen/R600/and.ll | 37 +- test/CodeGen/R600/array-ptr-calc-i64.ll | 18 + test/CodeGen/R600/atomic_load_add.ll | 23 + test/CodeGen/R600/atomic_load_sub.ll | 23 + test/CodeGen/R600/bfi_int.ll | 10 +- test/CodeGen/R600/big_alu.ll | 1174 + test/CodeGen/R600/bitcast.ll | 21 + test/CodeGen/R600/build_vector.ll | 34 + test/CodeGen/R600/call_fs.ll | 2 + test/CodeGen/R600/combine_vloads.ll | 42 + test/CodeGen/R600/complex-folding.ll | 19 + test/CodeGen/R600/dot4-folding.ll | 27 + test/CodeGen/R600/elf.ll | 4 +- test/CodeGen/R600/extload.ll | 51 + test/CodeGen/R600/fabs.ll | 56 +- test/CodeGen/R600/fadd.ll | 50 +- test/CodeGen/R600/fadd64.ll | 13 + test/CodeGen/R600/fcmp-cnd.ll | 2 +- test/CodeGen/R600/fcmp.ll | 2 +- test/CodeGen/R600/fcmp64.ll | 79 + test/CodeGen/R600/fconst64.ll | 12 + test/CodeGen/R600/fdiv.ll | 51 +- test/CodeGen/R600/fdiv64.ll | 14 + test/CodeGen/R600/fetch-limits.r600.ll | 48 + test/CodeGen/R600/fetch-limits.r700+.ll | 81 + test/CodeGen/R600/floor.ll | 14 +- test/CodeGen/R600/fma.ll | 31 + test/CodeGen/R600/fmad.ll | 22 +- test/CodeGen/R600/fmax.ll | 15 +- test/CodeGen/R600/fmin.ll | 13 +- test/CodeGen/R600/fmul.ll | 48 +- test/CodeGen/R600/fmul.v4f32.ll | 15 - test/CodeGen/R600/fmul64.ll | 13 + test/CodeGen/R600/fmuladd.ll | 31 + test/CodeGen/R600/fneg.ll | 61 + test/CodeGen/R600/fp64_to_sint.ll | 9 + test/CodeGen/R600/fp_to_sint.ll | 29 +- test/CodeGen/R600/fp_to_uint.ll | 31 +- test/CodeGen/R600/fpext.ll | 9 + test/CodeGen/R600/fptrunc.ll | 9 + test/CodeGen/R600/fsqrt.ll | 24 + test/CodeGen/R600/fsub.ll | 48 +- test/CodeGen/R600/fsub64.ll | 13 + test/CodeGen/R600/gep-address-space.ll | 40 + test/CodeGen/R600/icmp-select-sete-reverse-args.ll | 2 +- test/CodeGen/R600/imm.ll | 14 +- test/CodeGen/R600/indirect-addressing-si.ll | 48 + test/CodeGen/R600/insert_vector_elt.ll | 16 + test/CodeGen/R600/kcache-fold.ll | 18 +- test/CodeGen/R600/kernel-args.ll | 455 + test/CodeGen/R600/lds-output-queue.ll | 99 + test/CodeGen/R600/lds-size.ll | 26 + test/CodeGen/R600/lit.local.cfg | 12 +- test/CodeGen/R600/literals.ll | 191 +- test/CodeGen/R600/llvm.AMDGPU.barrier.local.ll | 24 + test/CodeGen/R600/llvm.AMDGPU.cube.ll | 59 + test/CodeGen/R600/llvm.AMDGPU.imax.ll | 21 + test/CodeGen/R600/llvm.AMDGPU.imin.ll | 21 + test/CodeGen/R600/llvm.AMDGPU.mul.ll | 16 +- test/CodeGen/R600/llvm.AMDGPU.tex.ll | 32 +- test/CodeGen/R600/llvm.AMDGPU.trunc.ll | 22 +- test/CodeGen/R600/llvm.AMDGPU.umax.ll | 21 + test/CodeGen/R600/llvm.AMDGPU.umin.ll | 21 + test/CodeGen/R600/llvm.SI.fs.interp.constant.ll | 2 +- test/CodeGen/R600/llvm.SI.imageload.ll | 131 + test/CodeGen/R600/llvm.SI.resinfo.ll | 110 + test/CodeGen/R600/llvm.SI.sample-masked.ll | 93 + test/CodeGen/R600/llvm.SI.sample.ll | 85 +- test/CodeGen/R600/llvm.SI.sampled.ll | 140 + test/CodeGen/R600/llvm.SI.tbuffer.store.ll | 44 + test/CodeGen/R600/llvm.SI.tid.ll | 16 + test/CodeGen/R600/llvm.cos.ll | 17 +- test/CodeGen/R600/llvm.floor.ll | 54 + test/CodeGen/R600/llvm.pow.ll | 20 +- test/CodeGen/R600/llvm.rint.ll | 54 + test/CodeGen/R600/llvm.round.ll | 41 + test/CodeGen/R600/llvm.sin.ll | 17 +- test/CodeGen/R600/llvm.sqrt.ll | 54 + test/CodeGen/R600/load-input-fold.ll | 118 + test/CodeGen/R600/load.ll | 669 +- test/CodeGen/R600/load.vec.ll | 24 + test/CodeGen/R600/load64.ll | 20 + test/CodeGen/R600/local-memory-two-objects.ll | 58 + test/CodeGen/R600/local-memory.ll | 50 + test/CodeGen/R600/loop-address.ll | 10 +- test/CodeGen/R600/lshl.ll | 4 +- test/CodeGen/R600/lshr.ll | 4 +- test/CodeGen/R600/mad_int24.ll | 20 + test/CodeGen/R600/mad_uint24.ll | 70 + test/CodeGen/R600/max-literals.ll | 67 + test/CodeGen/R600/mul.ll | 38 +- test/CodeGen/R600/mul_int24.ll | 19 + test/CodeGen/R600/mul_uint24.ll | 65 + test/CodeGen/R600/mulhu.ll | 8 +- test/CodeGen/R600/or.ll | 54 +- test/CodeGen/R600/packetizer.ll | 34 + test/CodeGen/R600/parallelandifcollapse.ll | 54 + test/CodeGen/R600/parallelorifcollapse.ll | 61 + test/CodeGen/R600/predicate-dp4.ll | 27 + test/CodeGen/R600/predicates.ll | 2 +- test/CodeGen/R600/private-memory.ll | 115 + test/CodeGen/R600/pv-packing.ll | 45 + test/CodeGen/R600/pv.ll | 63 +- test/CodeGen/R600/r600-encoding.ll | 19 +- test/CodeGen/R600/r600-export-fix.ll | 142 + test/CodeGen/R600/r600cfg.ll | 120 + test/CodeGen/R600/reciprocal.ll | 13 +- test/CodeGen/R600/rotr.ll | 37 + test/CodeGen/R600/rv7x0_count3.ll | 41 + test/CodeGen/R600/schedule-fs-loop-nested-if.ll | 15 +- test/CodeGen/R600/schedule-fs-loop-nested.ll | 2 +- test/CodeGen/R600/schedule-fs-loop.ll | 2 +- test/CodeGen/R600/schedule-if-2.ll | 2 +- test/CodeGen/R600/schedule-if.ll | 2 +- test/CodeGen/R600/schedule-vs-if-nested-loop.ll | 14 +- test/CodeGen/R600/select.ll | 46 + test/CodeGen/R600/selectcc-cnd.ll | 4 +- test/CodeGen/R600/selectcc-cnde-int.ll | 2 +- test/CodeGen/R600/selectcc-opt.ll | 5 +- test/CodeGen/R600/set-dx10.ll | 96 +- test/CodeGen/R600/setcc.ll | 327 +- test/CodeGen/R600/setcc64.ll | 263 + test/CodeGen/R600/seto.ll | 4 +- test/CodeGen/R600/setuo.ll | 4 +- test/CodeGen/R600/sgpr-copy-duplicate-operand.ll | 18 + test/CodeGen/R600/sgpr-copy.ll | 327 + test/CodeGen/R600/shared-op-cycle.ll | 32 + test/CodeGen/R600/shl.ll | 44 +- test/CodeGen/R600/short-args.ll | 41 - test/CodeGen/R600/si-annotate-cf-assertion.ll | 23 + test/CodeGen/R600/si-lod-bias.ll | 51 + test/CodeGen/R600/si-sgpr-spill.ll | 692 + test/CodeGen/R600/si-vector-hang.ll | 107 + test/CodeGen/R600/sign_extend.ll | 12 + test/CodeGen/R600/sint_to_fp.ll | 29 +- test/CodeGen/R600/sint_to_fp64.ll | 9 + test/CodeGen/R600/sra.ll | 55 +- test/CodeGen/R600/srl.ll | 42 +- test/CodeGen/R600/store-vector-ptrs.ll | 8 + test/CodeGen/R600/store.ll | 277 +- test/CodeGen/R600/store.r600.ll | 4 +- test/CodeGen/R600/structurize.ll | 83 + test/CodeGen/R600/structurize1.ll | 62 + test/CodeGen/R600/sub.ll | 37 +- test/CodeGen/R600/swizzle-export.ll | 129 + test/CodeGen/R600/tex-clause-antidep.ll | 25 + test/CodeGen/R600/texture-input-merge.ll | 31 + .../R600/trunc-vector-store-assertion-failure.ll | 20 + test/CodeGen/R600/trunc.ll | 30 + test/CodeGen/R600/udiv.ll | 38 +- test/CodeGen/R600/uint_to_fp.ll | 44 +- test/CodeGen/R600/unaligned-load-store.ll | 17 + test/CodeGen/R600/unsupported-cc.ll | 68 +- test/CodeGen/R600/urecip.ll | 2 +- test/CodeGen/R600/urem.ll | 27 +- test/CodeGen/R600/vertex-fetch-encoding.ll | 25 + test/CodeGen/R600/vselect.ll | 71 +- test/CodeGen/R600/vselect64.ll | 15 + test/CodeGen/R600/vtx-schedule.ll | 18 + test/CodeGen/R600/wait.ll | 37 + test/CodeGen/R600/work-item-intrinsics.ll | 211 + test/CodeGen/R600/wrong-transalu-pos-fix.ll | 86 + test/CodeGen/R600/xor.ll | 57 +- test/CodeGen/R600/zero_extend.ll | 18 + test/CodeGen/SI/sanity.ll | 37 - test/CodeGen/SPARC/2011-01-11-CC.ll | 110 +- test/CodeGen/SPARC/2011-01-11-Call.ll | 40 + test/CodeGen/SPARC/2011-01-11-FrameAddr.ll | 43 +- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll | 105 +- test/CodeGen/SPARC/2011-01-21-ByValArgs.ll | 2 +- test/CodeGen/SPARC/2011-01-22-SRet.ll | 10 +- test/CodeGen/SPARC/2013-05-17-CallFrame.ll | 26 + test/CodeGen/SPARC/64abi.ll | 37 +- test/CodeGen/SPARC/64bit.ll | 135 +- test/CodeGen/SPARC/64cond.ll | 89 +- test/CodeGen/SPARC/basictest.ll | 24 +- test/CodeGen/SPARC/blockaddr.ll | 77 + test/CodeGen/SPARC/constpool.ll | 15 +- test/CodeGen/SPARC/exception.ll | 112 + test/CodeGen/SPARC/float.ll | 249 + test/CodeGen/SPARC/fp128.ll | 234 + test/CodeGen/SPARC/globals.ll | 19 +- test/CodeGen/SPARC/leafproc.ll | 80 + test/CodeGen/SPARC/lit.local.cfg | 2 - test/CodeGen/SPARC/rem.ll | 39 + test/CodeGen/SPARC/setjmp.ll | 72 + test/CodeGen/SPARC/tls.ll | 73 + test/CodeGen/SPARC/varargs.ll | 1 + test/CodeGen/SystemZ/Large/branch-range-01.py | 105 + test/CodeGen/SystemZ/Large/branch-range-02.py | 82 + test/CodeGen/SystemZ/Large/branch-range-03.py | 107 + test/CodeGen/SystemZ/Large/branch-range-04.py | 111 + test/CodeGen/SystemZ/Large/branch-range-05.py | 109 + test/CodeGen/SystemZ/Large/branch-range-06.py | 109 + test/CodeGen/SystemZ/Large/branch-range-07.py | 68 + test/CodeGen/SystemZ/Large/branch-range-08.py | 69 + test/CodeGen/SystemZ/Large/branch-range-09.py | 107 + test/CodeGen/SystemZ/Large/branch-range-10.py | 111 + test/CodeGen/SystemZ/Large/branch-range-11.py | 127 + test/CodeGen/SystemZ/Large/branch-range-12.py | 127 + test/CodeGen/SystemZ/Large/lit.local.cfg | 10 + test/CodeGen/SystemZ/Large/spill-01.py | 40 + test/CodeGen/SystemZ/Large/spill-02.py | 73 + test/CodeGen/SystemZ/addr-01.ll | 16 +- test/CodeGen/SystemZ/addr-02.ll | 16 +- test/CodeGen/SystemZ/addr-03.ll | 10 +- test/CodeGen/SystemZ/alias-01.ll | 19 + test/CodeGen/SystemZ/alloca-01.ll | 42 +- test/CodeGen/SystemZ/alloca-02.ll | 35 +- test/CodeGen/SystemZ/and-01.ll | 70 +- test/CodeGen/SystemZ/and-02.ll | 189 +- test/CodeGen/SystemZ/and-03.ll | 64 +- test/CodeGen/SystemZ/and-04.ll | 153 +- test/CodeGen/SystemZ/and-05.ll | 26 +- test/CodeGen/SystemZ/and-06.ll | 16 +- test/CodeGen/SystemZ/and-07.ll | 39 + test/CodeGen/SystemZ/and-08.ll | 378 + test/CodeGen/SystemZ/args-01.ll | 33 +- test/CodeGen/SystemZ/args-02.ll | 33 +- test/CodeGen/SystemZ/args-03.ll | 33 +- test/CodeGen/SystemZ/args-04.ll | 26 +- test/CodeGen/SystemZ/args-05.ll | 8 +- test/CodeGen/SystemZ/args-06.ll | 12 +- test/CodeGen/SystemZ/asm-01.ll | 10 +- test/CodeGen/SystemZ/asm-02.ll | 8 +- test/CodeGen/SystemZ/asm-03.ll | 2 +- test/CodeGen/SystemZ/asm-04.ll | 2 +- test/CodeGen/SystemZ/asm-05.ll | 2 +- test/CodeGen/SystemZ/asm-06.ll | 8 +- test/CodeGen/SystemZ/asm-07.ll | 8 +- test/CodeGen/SystemZ/asm-08.ll | 8 +- test/CodeGen/SystemZ/asm-09.ll | 16 +- test/CodeGen/SystemZ/asm-10.ll | 6 +- test/CodeGen/SystemZ/asm-11.ll | 8 +- test/CodeGen/SystemZ/asm-12.ll | 8 +- test/CodeGen/SystemZ/asm-13.ll | 8 +- test/CodeGen/SystemZ/asm-14.ll | 8 +- test/CodeGen/SystemZ/asm-15.ll | 6 +- test/CodeGen/SystemZ/asm-16.ll | 6 +- test/CodeGen/SystemZ/asm-17.ll | 105 + test/CodeGen/SystemZ/asm-18.ll | 745 + test/CodeGen/SystemZ/atomic-load-01.ll | 2 +- test/CodeGen/SystemZ/atomic-load-02.ll | 2 +- test/CodeGen/SystemZ/atomic-load-03.ll | 2 +- test/CodeGen/SystemZ/atomic-load-04.ll | 2 +- test/CodeGen/SystemZ/atomic-store-01.ll | 2 +- test/CodeGen/SystemZ/atomic-store-02.ll | 2 +- test/CodeGen/SystemZ/atomic-store-03.ll | 4 +- test/CodeGen/SystemZ/atomic-store-04.ll | 4 +- test/CodeGen/SystemZ/atomicrmw-add-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-add-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-add-03.ll | 24 +- test/CodeGen/SystemZ/atomicrmw-add-04.ll | 28 +- test/CodeGen/SystemZ/atomicrmw-and-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-and-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-and-03.ll | 22 +- test/CodeGen/SystemZ/atomicrmw-and-04.ll | 136 +- test/CodeGen/SystemZ/atomicrmw-minmax-01.ll | 84 +- test/CodeGen/SystemZ/atomicrmw-minmax-02.ll | 84 +- test/CodeGen/SystemZ/atomicrmw-minmax-03.ll | 60 +- test/CodeGen/SystemZ/atomicrmw-minmax-04.ll | 54 +- test/CodeGen/SystemZ/atomicrmw-nand-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-nand-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-nand-03.ll | 22 +- test/CodeGen/SystemZ/atomicrmw-nand-04.ll | 160 +- test/CodeGen/SystemZ/atomicrmw-or-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-or-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-or-03.ll | 22 +- test/CodeGen/SystemZ/atomicrmw-or-04.ll | 38 +- test/CodeGen/SystemZ/atomicrmw-sub-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-sub-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-sub-03.ll | 24 +- test/CodeGen/SystemZ/atomicrmw-sub-04.ll | 28 +- test/CodeGen/SystemZ/atomicrmw-xchg-01.ll | 10 +- test/CodeGen/SystemZ/atomicrmw-xchg-02.ll | 10 +- test/CodeGen/SystemZ/atomicrmw-xchg-03.ll | 24 +- test/CodeGen/SystemZ/atomicrmw-xchg-04.ll | 18 +- test/CodeGen/SystemZ/atomicrmw-xor-01.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-xor-02.ll | 40 +- test/CodeGen/SystemZ/atomicrmw-xor-03.ll | 14 +- test/CodeGen/SystemZ/atomicrmw-xor-04.ll | 20 +- test/CodeGen/SystemZ/branch-01.ll | 4 +- test/CodeGen/SystemZ/branch-02.ll | 27 +- test/CodeGen/SystemZ/branch-03.ll | 16 +- test/CodeGen/SystemZ/branch-04.ll | 56 +- test/CodeGen/SystemZ/branch-05.ll | 5 +- test/CodeGen/SystemZ/branch-06.ll | 190 + test/CodeGen/SystemZ/branch-07.ll | 157 + test/CodeGen/SystemZ/branch-08.ll | 46 + test/CodeGen/SystemZ/branch-09.ll | 62 + test/CodeGen/SystemZ/branch-10.ll | 62 + test/CodeGen/SystemZ/bswap-01.ll | 8 +- test/CodeGen/SystemZ/bswap-02.ll | 103 +- test/CodeGen/SystemZ/bswap-03.ll | 103 +- test/CodeGen/SystemZ/bswap-04.ll | 50 +- test/CodeGen/SystemZ/bswap-05.ll | 50 +- test/CodeGen/SystemZ/call-01.ll | 2 +- test/CodeGen/SystemZ/call-02.ll | 2 +- test/CodeGen/SystemZ/call-03.ll | 125 + test/CodeGen/SystemZ/cmpxchg-01.ll | 13 +- test/CodeGen/SystemZ/cmpxchg-02.ll | 13 +- test/CodeGen/SystemZ/cmpxchg-03.ll | 24 +- test/CodeGen/SystemZ/cmpxchg-04.ll | 18 +- test/CodeGen/SystemZ/cond-load-01.ll | 130 + test/CodeGen/SystemZ/cond-load-02.ll | 130 + test/CodeGen/SystemZ/cond-move-01.ll | 48 + test/CodeGen/SystemZ/cond-store-01.ll | 398 + test/CodeGen/SystemZ/cond-store-02.ll | 398 + test/CodeGen/SystemZ/cond-store-03.ll | 322 + test/CodeGen/SystemZ/cond-store-04.ll | 214 + test/CodeGen/SystemZ/cond-store-05.ll | 213 + test/CodeGen/SystemZ/cond-store-06.ll | 213 + test/CodeGen/SystemZ/cond-store-07.ll | 186 + test/CodeGen/SystemZ/cond-store-08.ll | 124 + test/CodeGen/SystemZ/fp-abs-01.ll | 6 +- test/CodeGen/SystemZ/fp-abs-02.ll | 6 +- test/CodeGen/SystemZ/fp-add-01.ll | 60 +- test/CodeGen/SystemZ/fp-add-02.ll | 60 +- test/CodeGen/SystemZ/fp-add-03.ll | 2 +- test/CodeGen/SystemZ/fp-cmp-01.ll | 258 +- test/CodeGen/SystemZ/fp-cmp-02.ll | 114 +- test/CodeGen/SystemZ/fp-cmp-03.ll | 24 +- test/CodeGen/SystemZ/fp-cmp-04.ll | 348 + test/CodeGen/SystemZ/fp-const-01.ll | 6 +- test/CodeGen/SystemZ/fp-const-02.ll | 6 +- test/CodeGen/SystemZ/fp-const-03.ll | 2 +- test/CodeGen/SystemZ/fp-const-04.ll | 2 +- test/CodeGen/SystemZ/fp-const-05.ll | 2 +- test/CodeGen/SystemZ/fp-const-06.ll | 2 +- test/CodeGen/SystemZ/fp-const-07.ll | 2 +- test/CodeGen/SystemZ/fp-const-08.ll | 2 +- test/CodeGen/SystemZ/fp-const-09.ll | 2 +- test/CodeGen/SystemZ/fp-conv-01.ll | 10 +- test/CodeGen/SystemZ/fp-conv-02.ll | 93 +- test/CodeGen/SystemZ/fp-conv-03.ll | 93 +- test/CodeGen/SystemZ/fp-conv-04.ll | 93 +- test/CodeGen/SystemZ/fp-conv-05.ll | 6 +- test/CodeGen/SystemZ/fp-conv-06.ll | 6 +- test/CodeGen/SystemZ/fp-conv-07.ll | 6 +- test/CodeGen/SystemZ/fp-conv-08.ll | 8 +- test/CodeGen/SystemZ/fp-conv-09.ll | 6 +- test/CodeGen/SystemZ/fp-conv-10.ll | 6 +- test/CodeGen/SystemZ/fp-conv-11.ll | 6 +- test/CodeGen/SystemZ/fp-conv-12.ll | 6 +- test/CodeGen/SystemZ/fp-copysign-01.ll | 18 +- test/CodeGen/SystemZ/fp-div-01.ll | 60 +- test/CodeGen/SystemZ/fp-div-02.ll | 60 +- test/CodeGen/SystemZ/fp-div-03.ll | 2 +- test/CodeGen/SystemZ/fp-move-01.ll | 6 +- test/CodeGen/SystemZ/fp-move-02.ll | 316 +- test/CodeGen/SystemZ/fp-move-03.ll | 20 +- test/CodeGen/SystemZ/fp-move-04.ll | 20 +- test/CodeGen/SystemZ/fp-move-05.ll | 22 +- test/CodeGen/SystemZ/fp-move-06.ll | 20 +- test/CodeGen/SystemZ/fp-move-07.ll | 20 +- test/CodeGen/SystemZ/fp-move-08.ll | 22 +- test/CodeGen/SystemZ/fp-move-09.ll | 62 + test/CodeGen/SystemZ/fp-mul-01.ll | 60 +- test/CodeGen/SystemZ/fp-mul-02.ll | 132 +- test/CodeGen/SystemZ/fp-mul-03.ll | 60 +- test/CodeGen/SystemZ/fp-mul-04.ll | 142 +- test/CodeGen/SystemZ/fp-mul-05.ll | 2 +- test/CodeGen/SystemZ/fp-mul-06.ll | 16 +- test/CodeGen/SystemZ/fp-mul-07.ll | 16 +- test/CodeGen/SystemZ/fp-mul-08.ll | 16 +- test/CodeGen/SystemZ/fp-mul-09.ll | 16 +- test/CodeGen/SystemZ/fp-neg-01.ll | 6 +- test/CodeGen/SystemZ/fp-round-01.ll | 132 +- test/CodeGen/SystemZ/fp-round-02.ll | 195 + test/CodeGen/SystemZ/fp-sqrt-01.ll | 110 +- test/CodeGen/SystemZ/fp-sqrt-02.ll | 108 +- test/CodeGen/SystemZ/fp-sqrt-03.ll | 2 +- test/CodeGen/SystemZ/fp-sub-01.ll | 60 +- test/CodeGen/SystemZ/fp-sub-02.ll | 60 +- test/CodeGen/SystemZ/fp-sub-03.ll | 2 +- test/CodeGen/SystemZ/frame-01.ll | 70 +- test/CodeGen/SystemZ/frame-02.ll | 8 +- test/CodeGen/SystemZ/frame-03.ll | 8 +- test/CodeGen/SystemZ/frame-04.ll | 8 +- test/CodeGen/SystemZ/frame-05.ll | 8 +- test/CodeGen/SystemZ/frame-06.ll | 8 +- test/CodeGen/SystemZ/frame-07.ll | 22 +- test/CodeGen/SystemZ/frame-08.ll | 44 +- test/CodeGen/SystemZ/frame-09.ll | 28 +- test/CodeGen/SystemZ/frame-10.ll | 2 +- test/CodeGen/SystemZ/frame-11.ll | 2 +- test/CodeGen/SystemZ/frame-13.ll | 182 +- test/CodeGen/SystemZ/frame-14.ll | 172 +- test/CodeGen/SystemZ/frame-15.ll | 203 +- test/CodeGen/SystemZ/frame-16.ll | 182 +- test/CodeGen/SystemZ/frame-17.ll | 6 +- test/CodeGen/SystemZ/frame-18.ll | 9 +- test/CodeGen/SystemZ/insert-01.ll | 34 +- test/CodeGen/SystemZ/insert-02.ll | 34 +- test/CodeGen/SystemZ/insert-03.ll | 12 +- test/CodeGen/SystemZ/insert-04.ll | 24 +- test/CodeGen/SystemZ/insert-05.ll | 38 +- test/CodeGen/SystemZ/insert-06.ll | 39 +- test/CodeGen/SystemZ/int-abs-01.ll | 83 + test/CodeGen/SystemZ/int-add-01.ll | 20 +- test/CodeGen/SystemZ/int-add-02.ll | 70 +- test/CodeGen/SystemZ/int-add-03.ll | 94 +- test/CodeGen/SystemZ/int-add-04.ll | 94 +- test/CodeGen/SystemZ/int-add-05.ll | 64 +- test/CodeGen/SystemZ/int-add-06.ll | 20 +- test/CodeGen/SystemZ/int-add-07.ll | 28 +- test/CodeGen/SystemZ/int-add-08.ll | 50 +- test/CodeGen/SystemZ/int-add-09.ll | 18 +- test/CodeGen/SystemZ/int-add-10.ll | 38 +- test/CodeGen/SystemZ/int-add-11.ll | 191 +- test/CodeGen/SystemZ/int-add-12.ll | 186 +- test/CodeGen/SystemZ/int-add-13.ll | 39 + test/CodeGen/SystemZ/int-add-14.ll | 67 + test/CodeGen/SystemZ/int-add-15.ll | 67 + test/CodeGen/SystemZ/int-add-16.ll | 93 + test/CodeGen/SystemZ/int-cmp-01.ll | 34 +- test/CodeGen/SystemZ/int-cmp-02.ll | 80 +- test/CodeGen/SystemZ/int-cmp-03.ll | 58 +- test/CodeGen/SystemZ/int-cmp-04.ll | 28 +- test/CodeGen/SystemZ/int-cmp-05.ll | 157 +- test/CodeGen/SystemZ/int-cmp-06.ll | 171 +- test/CodeGen/SystemZ/int-cmp-07.ll | 46 +- test/CodeGen/SystemZ/int-cmp-08.ll | 46 +- test/CodeGen/SystemZ/int-cmp-09.ll | 161 +- test/CodeGen/SystemZ/int-cmp-10.ll | 38 +- test/CodeGen/SystemZ/int-cmp-11.ll | 115 +- test/CodeGen/SystemZ/int-cmp-12.ll | 45 +- test/CodeGen/SystemZ/int-cmp-13.ll | 122 +- test/CodeGen/SystemZ/int-cmp-14.ll | 122 +- test/CodeGen/SystemZ/int-cmp-15.ll | 58 +- test/CodeGen/SystemZ/int-cmp-16.ll | 32 +- test/CodeGen/SystemZ/int-cmp-17.ll | 32 +- test/CodeGen/SystemZ/int-cmp-18.ll | 32 +- test/CodeGen/SystemZ/int-cmp-19.ll | 32 +- test/CodeGen/SystemZ/int-cmp-20.ll | 64 +- test/CodeGen/SystemZ/int-cmp-21.ll | 52 +- test/CodeGen/SystemZ/int-cmp-22.ll | 38 +- test/CodeGen/SystemZ/int-cmp-23.ll | 24 +- test/CodeGen/SystemZ/int-cmp-24.ll | 16 +- test/CodeGen/SystemZ/int-cmp-25.ll | 16 +- test/CodeGen/SystemZ/int-cmp-26.ll | 32 +- test/CodeGen/SystemZ/int-cmp-27.ll | 32 +- test/CodeGen/SystemZ/int-cmp-28.ll | 32 +- test/CodeGen/SystemZ/int-cmp-29.ll | 32 +- test/CodeGen/SystemZ/int-cmp-30.ll | 52 +- test/CodeGen/SystemZ/int-cmp-31.ll | 52 +- test/CodeGen/SystemZ/int-cmp-32.ll | 66 +- test/CodeGen/SystemZ/int-cmp-33.ll | 36 +- test/CodeGen/SystemZ/int-cmp-34.ll | 66 +- test/CodeGen/SystemZ/int-cmp-35.ll | 36 +- test/CodeGen/SystemZ/int-cmp-36.ll | 54 +- test/CodeGen/SystemZ/int-cmp-37.ll | 54 +- test/CodeGen/SystemZ/int-cmp-38.ll | 73 +- test/CodeGen/SystemZ/int-cmp-39.ll | 54 +- test/CodeGen/SystemZ/int-cmp-40.ll | 54 +- test/CodeGen/SystemZ/int-cmp-41.ll | 54 +- test/CodeGen/SystemZ/int-cmp-42.ll | 54 +- test/CodeGen/SystemZ/int-cmp-43.ll | 54 +- test/CodeGen/SystemZ/int-cmp-44.ll | 799 + test/CodeGen/SystemZ/int-cmp-45.ll | 115 + test/CodeGen/SystemZ/int-cmp-46.ll | 491 + test/CodeGen/SystemZ/int-cmp-47.ll | 234 + test/CodeGen/SystemZ/int-cmp-48.ll | 245 + test/CodeGen/SystemZ/int-cmp-49.ll | 49 + test/CodeGen/SystemZ/int-const-01.ll | 44 +- test/CodeGen/SystemZ/int-const-02.ll | 94 +- test/CodeGen/SystemZ/int-const-03.ll | 44 +- test/CodeGen/SystemZ/int-const-04.ll | 42 +- test/CodeGen/SystemZ/int-const-05.ll | 39 +- test/CodeGen/SystemZ/int-const-06.ll | 40 +- test/CodeGen/SystemZ/int-conv-01.ll | 116 +- test/CodeGen/SystemZ/int-conv-02.ll | 125 +- test/CodeGen/SystemZ/int-conv-03.ll | 116 +- test/CodeGen/SystemZ/int-conv-04.ll | 120 +- test/CodeGen/SystemZ/int-conv-05.ll | 122 +- test/CodeGen/SystemZ/int-conv-06.ll | 125 +- test/CodeGen/SystemZ/int-conv-07.ll | 116 +- test/CodeGen/SystemZ/int-conv-08.ll | 120 +- test/CodeGen/SystemZ/int-conv-09.ll | 22 +- test/CodeGen/SystemZ/int-conv-10.ll | 26 +- test/CodeGen/SystemZ/int-conv-11.ll | 350 + test/CodeGen/SystemZ/int-div-01.ll | 89 +- test/CodeGen/SystemZ/int-div-02.ll | 69 +- test/CodeGen/SystemZ/int-div-03.ll | 47 +- test/CodeGen/SystemZ/int-div-04.ll | 72 +- test/CodeGen/SystemZ/int-div-05.ll | 72 +- test/CodeGen/SystemZ/int-div-06.ll | 56 + test/CodeGen/SystemZ/int-move-01.ll | 8 +- test/CodeGen/SystemZ/int-move-02.ll | 20 +- test/CodeGen/SystemZ/int-move-03.ll | 14 +- test/CodeGen/SystemZ/int-move-04.ll | 24 +- test/CodeGen/SystemZ/int-move-05.ll | 24 +- test/CodeGen/SystemZ/int-move-06.ll | 20 +- test/CodeGen/SystemZ/int-move-07.ll | 14 +- test/CodeGen/SystemZ/int-move-08.ll | 93 +- test/CodeGen/SystemZ/int-move-09.ll | 99 +- test/CodeGen/SystemZ/int-mul-01.ll | 20 +- test/CodeGen/SystemZ/int-mul-02.ll | 67 +- test/CodeGen/SystemZ/int-mul-03.ll | 94 +- test/CodeGen/SystemZ/int-mul-04.ll | 61 +- test/CodeGen/SystemZ/int-mul-05.ll | 34 +- test/CodeGen/SystemZ/int-mul-06.ll | 34 +- test/CodeGen/SystemZ/int-mul-07.ll | 8 +- test/CodeGen/SystemZ/int-mul-08.ll | 110 +- test/CodeGen/SystemZ/int-neg-01.ll | 8 +- test/CodeGen/SystemZ/int-neg-02.ll | 91 + test/CodeGen/SystemZ/int-sub-01.ll | 70 +- test/CodeGen/SystemZ/int-sub-02.ll | 94 +- test/CodeGen/SystemZ/int-sub-03.ll | 94 +- test/CodeGen/SystemZ/int-sub-04.ll | 64 +- test/CodeGen/SystemZ/int-sub-05.ll | 53 +- test/CodeGen/SystemZ/int-sub-06.ll | 20 +- test/CodeGen/SystemZ/int-sub-07.ll | 131 + test/CodeGen/SystemZ/int-sub-08.ll | 39 + test/CodeGen/SystemZ/int-sub-09.ll | 22 + test/CodeGen/SystemZ/la-01.ll | 31 +- test/CodeGen/SystemZ/la-02.ll | 16 +- test/CodeGen/SystemZ/la-03.ll | 16 +- test/CodeGen/SystemZ/la-04.ll | 2 +- test/CodeGen/SystemZ/lit.local.cfg | 2 - test/CodeGen/SystemZ/loop-01.ll | 124 + test/CodeGen/SystemZ/memchr-01.ll | 21 + test/CodeGen/SystemZ/memchr-02.ll | 57 + test/CodeGen/SystemZ/memcmp-01.ll | 221 + test/CodeGen/SystemZ/memcmp-02.ll | 139 + test/CodeGen/SystemZ/memcpy-01.ll | 235 + test/CodeGen/SystemZ/memcpy-02.ll | 392 + test/CodeGen/SystemZ/memset-01.ll | 160 + test/CodeGen/SystemZ/memset-02.ll | 162 + test/CodeGen/SystemZ/memset-03.ll | 382 + test/CodeGen/SystemZ/memset-04.ll | 398 + test/CodeGen/SystemZ/or-01.ll | 70 +- test/CodeGen/SystemZ/or-02.ll | 14 +- test/CodeGen/SystemZ/or-03.ll | 64 +- test/CodeGen/SystemZ/or-04.ll | 38 +- test/CodeGen/SystemZ/or-05.ll | 26 +- test/CodeGen/SystemZ/or-06.ll | 16 +- test/CodeGen/SystemZ/or-07.ll | 39 + test/CodeGen/SystemZ/or-08.ll | 57 + test/CodeGen/SystemZ/prefetch-01.ll | 87 + test/CodeGen/SystemZ/risbg-01.ll | 472 + test/CodeGen/SystemZ/risbg-02.ll | 93 + test/CodeGen/SystemZ/rnsbg-01.ll | 257 + test/CodeGen/SystemZ/rosbg-01.ll | 110 + test/CodeGen/SystemZ/rxsbg-01.ll | 112 + test/CodeGen/SystemZ/setcc-01.ll | 74 + test/CodeGen/SystemZ/setcc-02.ll | 174 + test/CodeGen/SystemZ/shift-01.ll | 22 +- test/CodeGen/SystemZ/shift-02.ll | 22 +- test/CodeGen/SystemZ/shift-03.ll | 22 +- test/CodeGen/SystemZ/shift-04.ll | 28 +- test/CodeGen/SystemZ/shift-05.ll | 28 +- test/CodeGen/SystemZ/shift-06.ll | 28 +- test/CodeGen/SystemZ/shift-07.ll | 28 +- test/CodeGen/SystemZ/shift-08.ll | 28 +- test/CodeGen/SystemZ/shift-09.ll | 63 + test/CodeGen/SystemZ/shift-10.ll | 78 + test/CodeGen/SystemZ/spill-01.ll | 548 + test/CodeGen/SystemZ/strcmp-01.ll | 70 + test/CodeGen/SystemZ/strcmp-02.ll | 72 + test/CodeGen/SystemZ/strcpy-01.ll | 50 + test/CodeGen/SystemZ/strlen-01.ll | 39 + test/CodeGen/SystemZ/strlen-02.ll | 39 + test/CodeGen/SystemZ/tls-01.ll | 2 +- test/CodeGen/SystemZ/unaligned-01.ll | 62 + test/CodeGen/SystemZ/xor-01.ll | 70 +- test/CodeGen/SystemZ/xor-02.ll | 8 +- test/CodeGen/SystemZ/xor-03.ll | 64 +- test/CodeGen/SystemZ/xor-04.ll | 14 +- test/CodeGen/SystemZ/xor-05.ll | 26 +- test/CodeGen/SystemZ/xor-06.ll | 16 +- test/CodeGen/SystemZ/xor-07.ll | 39 + test/CodeGen/SystemZ/xor-08.ll | 57 + test/CodeGen/Thumb/2009-08-20-ISelBug.ll | 2 +- test/CodeGen/Thumb/2010-07-15-debugOrdering.ll | 150 +- test/CodeGen/Thumb/2012-04-26-M0ISelBug.ll | 2 +- test/CodeGen/Thumb/PR17309.ll | 57 + test/CodeGen/Thumb/barrier.ll | 6 +- test/CodeGen/Thumb/dyn-stackalloc.ll | 4 +- test/CodeGen/Thumb/ispositive.ll | 2 +- test/CodeGen/Thumb/large-stack.ll | 12 +- test/CodeGen/Thumb/ldr_frame.ll | 8 +- test/CodeGen/Thumb/lit.local.cfg | 2 - test/CodeGen/Thumb/pop.ll | 2 +- test/CodeGen/Thumb/push.ll | 2 +- test/CodeGen/Thumb/rev.ll | 4 +- test/CodeGen/Thumb/select.ll | 28 +- test/CodeGen/Thumb/trap.ll | 2 +- test/CodeGen/Thumb2/2009-07-21-ISelBug.ll | 2 +- test/CodeGen/Thumb2/2009-08-01-WrongLDRBOpc.ll | 2 +- test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll | 2 +- test/CodeGen/Thumb2/2009-09-28-ITBlockBug.ll | 2 +- test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll | 2 +- test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll | 4 +- test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll | 6 +- test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll | 2 +- .../CodeGen/Thumb2/2010-08-10-VarSizedAllocaBug.ll | 4 +- test/CodeGen/Thumb2/2010-11-22-EpilogueBug.ll | 2 +- test/CodeGen/Thumb2/2011-04-21-FILoweringBug.ll | 2 +- test/CodeGen/Thumb2/2012-01-13-CBNZBug.ll | 2 +- .../2013-03-06-vector-sext-operand-scalarize.ll | 4 +- test/CodeGen/Thumb2/buildvector-crash.ll | 2 +- test/CodeGen/Thumb2/carry.ll | 6 +- test/CodeGen/Thumb2/cross-rc-coalescing-2.ll | 2 +- test/CodeGen/Thumb2/div.ll | 20 +- test/CodeGen/Thumb2/large-call.ll | 2 +- test/CodeGen/Thumb2/large-stack.ll | 12 +- test/CodeGen/Thumb2/lit.local.cfg | 2 - test/CodeGen/Thumb2/longMACt.ll | 8 +- test/CodeGen/Thumb2/lsr-deficiency.ll | 2 +- test/CodeGen/Thumb2/machine-licm.ll | 6 +- test/CodeGen/Thumb2/mul_const.ll | 4 +- test/CodeGen/Thumb2/pic-load.ll | 2 +- test/CodeGen/Thumb2/tail-call-r9.ll | 14 + test/CodeGen/Thumb2/thumb2-adc.ll | 12 +- test/CodeGen/Thumb2/thumb2-add.ll | 16 +- test/CodeGen/Thumb2/thumb2-add2.ll | 10 +- test/CodeGen/Thumb2/thumb2-add3.ll | 2 +- test/CodeGen/Thumb2/thumb2-add4.ll | 10 +- test/CodeGen/Thumb2/thumb2-add5.ll | 10 +- test/CodeGen/Thumb2/thumb2-add6.ll | 2 +- test/CodeGen/Thumb2/thumb2-and.ll | 10 +- test/CodeGen/Thumb2/thumb2-and2.ll | 10 +- test/CodeGen/Thumb2/thumb2-asr.ll | 2 +- test/CodeGen/Thumb2/thumb2-asr2.ll | 2 +- test/CodeGen/Thumb2/thumb2-bcc.ll | 2 +- test/CodeGen/Thumb2/thumb2-bfc.ll | 8 +- test/CodeGen/Thumb2/thumb2-bic.ll | 24 +- test/CodeGen/Thumb2/thumb2-branch.ll | 30 +- test/CodeGen/Thumb2/thumb2-call-tc.ll | 12 +- test/CodeGen/Thumb2/thumb2-call.ll | 8 +- test/CodeGen/Thumb2/thumb2-clz.ll | 2 +- test/CodeGen/Thumb2/thumb2-cmn.ll | 18 +- test/CodeGen/Thumb2/thumb2-cmn2.ll | 8 +- test/CodeGen/Thumb2/thumb2-cmp.ll | 12 +- test/CodeGen/Thumb2/thumb2-cmp2.ll | 12 +- test/CodeGen/Thumb2/thumb2-eor.ll | 14 +- test/CodeGen/Thumb2/thumb2-eor2.ll | 10 +- test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll | 6 +- test/CodeGen/Thumb2/thumb2-ifcvt1.ll | 11 +- test/CodeGen/Thumb2/thumb2-ifcvt2.ll | 16 +- test/CodeGen/Thumb2/thumb2-ifcvt3.ll | 2 + test/CodeGen/Thumb2/thumb2-ldm.ll | 6 +- test/CodeGen/Thumb2/thumb2-ldr.ll | 14 +- test/CodeGen/Thumb2/thumb2-ldrb.ll | 14 +- test/CodeGen/Thumb2/thumb2-ldrh.ll | 14 +- test/CodeGen/Thumb2/thumb2-lsl.ll | 2 +- test/CodeGen/Thumb2/thumb2-lsl2.ll | 2 +- test/CodeGen/Thumb2/thumb2-lsr.ll | 2 +- test/CodeGen/Thumb2/thumb2-lsr2.ll | 2 +- test/CodeGen/Thumb2/thumb2-mla.ll | 8 +- test/CodeGen/Thumb2/thumb2-mls.ll | 4 +- test/CodeGen/Thumb2/thumb2-mov.ll | 60 +- test/CodeGen/Thumb2/thumb2-mul.ll | 4 +- test/CodeGen/Thumb2/thumb2-mvn.ll | 8 +- test/CodeGen/Thumb2/thumb2-mvn2.ll | 12 +- test/CodeGen/Thumb2/thumb2-neg.ll | 2 +- test/CodeGen/Thumb2/thumb2-orn.ll | 16 +- test/CodeGen/Thumb2/thumb2-orn2.ll | 8 +- test/CodeGen/Thumb2/thumb2-orr.ll | 10 +- test/CodeGen/Thumb2/thumb2-orr2.ll | 10 +- test/CodeGen/Thumb2/thumb2-pack.ll | 25 +- test/CodeGen/Thumb2/thumb2-rev.ll | 4 +- test/CodeGen/Thumb2/thumb2-ror.ll | 4 +- test/CodeGen/Thumb2/thumb2-rsb.ll | 8 +- test/CodeGen/Thumb2/thumb2-rsb2.ll | 10 +- test/CodeGen/Thumb2/thumb2-sbc.ll | 2 +- test/CodeGen/Thumb2/thumb2-select.ll | 41 +- test/CodeGen/Thumb2/thumb2-spill-q.ll | 2 +- test/CodeGen/Thumb2/thumb2-str.ll | 16 +- test/CodeGen/Thumb2/thumb2-str_post.ll | 4 +- test/CodeGen/Thumb2/thumb2-strb.ll | 16 +- test/CodeGen/Thumb2/thumb2-strh.ll | 16 +- test/CodeGen/Thumb2/thumb2-sub.ll | 12 +- test/CodeGen/Thumb2/thumb2-sub2.ll | 2 +- test/CodeGen/Thumb2/thumb2-sub4.ll | 10 +- test/CodeGen/Thumb2/thumb2-sub5.ll | 2 +- test/CodeGen/Thumb2/thumb2-sxt-uxt.ll | 8 +- test/CodeGen/Thumb2/thumb2-tbb.ll | 2 +- test/CodeGen/Thumb2/thumb2-tbh.ll | 2 +- test/CodeGen/Thumb2/thumb2-teq.ll | 10 +- test/CodeGen/Thumb2/thumb2-tst.ll | 10 +- test/CodeGen/Thumb2/thumb2-tst2.ll | 12 +- test/CodeGen/Thumb2/tls2.ll | 8 +- test/CodeGen/Thumb2/v8_IT_1.ll | 17 + test/CodeGen/Thumb2/v8_IT_2.ll | 38 + test/CodeGen/Thumb2/v8_IT_3.ll | 77 + test/CodeGen/Thumb2/v8_IT_4.ll | 45 + test/CodeGen/Thumb2/v8_IT_5.ll | 63 + test/CodeGen/X86/2006-05-02-InstrSched1.ll | 6 +- test/CodeGen/X86/2006-05-11-InstrSched.ll | 2 +- test/CodeGen/X86/2006-11-12-CSRetCC.ll | 2 +- test/CodeGen/X86/2007-01-08-InstrSched.ll | 4 +- test/CodeGen/X86/2007-02-04-OrAddrMode.ll | 4 +- .../X86/2007-02-23-DAGCombine-Miscompile.ll | 2 +- .../CodeGen/X86/2007-03-24-InlineAsmXConstraint.ll | 2 +- test/CodeGen/X86/2007-05-07-InvokeSRet.ll | 19 - test/CodeGen/X86/2007-09-06-ExtWeakAliasee.ll | 13 +- test/CodeGen/X86/2007-09-27-LDIntrinsics.ll | 4 +- test/CodeGen/X86/2007-10-12-CoalesceExtSubReg.ll | 6 +- test/CodeGen/X86/2007-10-12-SpillerUnfold2.ll | 2 +- test/CodeGen/X86/2008-01-08-SchedulerCrash.ll | 2 +- test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll | 99 - test/CodeGen/X86/2008-03-14-SpillerCrash.ll | 4 +- test/CodeGen/X86/2008-04-24-pblendw-fold-crash.ll | 2 +- test/CodeGen/X86/2008-04-26-Asm-Optimize-Imm.ll | 2 +- test/CodeGen/X86/2008-05-22-FoldUnalignedLoad.ll | 2 +- test/CodeGen/X86/2008-07-19-movups-spills.ll | 673 +- test/CodeGen/X86/2008-08-19-SubAndFetch.ll | 2 +- test/CodeGen/X86/2008-08-31-EH_RETURN32.ll | 2 +- test/CodeGen/X86/2008-09-11-CoalescerBug2.ll | 12 + test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll | 18 +- .../X86/2009-02-12-InlineAsm-nieZ-constraints.ll | 2 +- test/CodeGen/X86/2009-02-26-MachineLICMBug.ll | 10 +- test/CodeGen/X86/2009-03-23-MultiUseSched.ll | 2 +- test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll | 2 +- test/CodeGen/X86/2009-05-23-dagcombine-shifts.ll | 2 +- test/CodeGen/X86/2009-09-21-NoSpillLoopCount.ll | 2 +- test/CodeGen/X86/2009-10-16-Scope.ll | 12 +- test/CodeGen/X86/2009-11-16-MachineLICM.ll | 2 +- test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll | 2 +- test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll | 4 +- test/CodeGen/X86/2009-12-11-TLSNoRedZone.ll | 2 +- test/CodeGen/X86/2010-01-08-Atomic64Bug.ll | 2 +- test/CodeGen/X86/2010-01-18-DbgValue.ll | 15 +- test/CodeGen/X86/2010-02-01-DbgValueCrash.ll | 24 +- test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll | 6 +- test/CodeGen/X86/2010-02-23-DAGCombineBug.ll | 2 +- test/CodeGen/X86/2010-04-08-CoalescerBug.ll | 2 +- test/CodeGen/X86/2010-05-25-DotDebugLoc.ll | 11 +- test/CodeGen/X86/2010-05-26-DotDebugLoc.ll | 37 +- test/CodeGen/X86/2010-05-28-Crash.ll | 23 +- test/CodeGen/X86/2010-06-01-DeadArg-DbgInfo.ll | 43 +- test/CodeGen/X86/2010-07-06-DbgCrash.ll | 22 +- test/CodeGen/X86/2010-07-29-SetccSimplify.ll | 2 +- test/CodeGen/X86/2010-08-04-StackVariable.ll | 56 +- test/CodeGen/X86/2010-09-16-EmptyFilename.ll | 19 +- test/CodeGen/X86/2010-09-17-SideEffectsInChain.ll | 8 +- test/CodeGen/X86/2010-11-02-DbgParameter.ll | 21 +- test/CodeGen/X86/2010-12-02-MC-Set.ll | 14 +- test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll | 19 +- test/CodeGen/X86/2011-04-19-sclr-bb.ll | 2 +- test/CodeGen/X86/2011-05-09-loaduse.ll | 2 +- .../CodeGen/X86/2011-05-26-UnreachableBlockElim.ll | 15 +- test/CodeGen/X86/2011-06-03-x87chain.ll | 18 + .../X86/2011-07-13-BadFrameIndexDisplacement.ll | 2 +- test/CodeGen/X86/2011-09-14-valcoalesce.ll | 37 +- test/CodeGen/X86/2011-09-18-sse2cmp.ll | 2 +- test/CodeGen/X86/2011-09-21-setcc-bug.ll | 2 +- test/CodeGen/X86/2011-10-11-srl.ll | 2 +- test/CodeGen/X86/2011-10-12-MachineCSE.ll | 29 +- .../X86/2011-10-18-FastISel-VectorParams.ll | 2 +- test/CodeGen/X86/2011-10-19-LegelizeLoad.ll | 3 +- test/CodeGen/X86/2011-10-27-tstore.ll | 2 +- test/CodeGen/X86/2011-10-30-padd.ll | 4 +- .../X86/2011-12-06-AVXVectorExtractCombine.ll | 2 +- test/CodeGen/X86/2011-12-15-vec_shift.ll | 4 +- .../2011-12-26-extractelement-duplicate-load.ll | 4 +- test/CodeGen/X86/2011-20-21-zext-ui2fp.ll | 2 +- test/CodeGen/X86/2012-01-11-split-cv.ll | 2 +- test/CodeGen/X86/2012-01-16-mfence-nosse-flags.ll | 2 +- test/CodeGen/X86/2012-01-18-vbitcast.ll | 2 +- test/CodeGen/X86/2012-02-20-MachineCPBug.ll | 78 - test/CodeGen/X86/2012-04-26-sdglue.ll | 6 +- test/CodeGen/X86/2012-05-17-TwoAddressBug.ll | 2 +- test/CodeGen/X86/2012-07-10-extload64.ll | 4 +- test/CodeGen/X86/2012-07-15-broadcastfold.ll | 2 +- test/CodeGen/X86/2012-08-07-CmpISelBug.ll | 2 +- test/CodeGen/X86/2012-08-16-setcc.ll | 8 +- test/CodeGen/X86/2012-08-17-legalizer-crash.ll | 3 +- test/CodeGen/X86/2012-1-10-buildvector.ll | 4 +- test/CodeGen/X86/2012-11-30-handlemove-dbg.ll | 8 +- test/CodeGen/X86/2012-11-30-misched-dbg.ll | 8 +- test/CodeGen/X86/2012-11-30-regpres-dbg.ll | 10 +- test/CodeGen/X86/2013-03-13-VEX-DestReg.ll | 2 +- .../X86/2013-10-14-FastISel-incorrect-vreg.ll | 132 + test/CodeGen/X86/3addr-16bit.ll | 23 +- test/CodeGen/X86/3addr-or.ll | 10 +- test/CodeGen/X86/GC/lit.local.cfg | 2 - test/CodeGen/X86/GC/ocaml-gc-assert.ll | 21 + test/CodeGen/X86/GC/ocaml-gc.ll | 20 +- test/CodeGen/X86/MachineSink-CritEdge.ll | 4 +- test/CodeGen/X86/MachineSink-DbgValue.ll | 15 +- test/CodeGen/X86/MergeConsecutiveStores.ll | 10 +- test/CodeGen/X86/StackColoring-dbg.ll | 9 +- test/CodeGen/X86/StackColoring.ll | 43 +- test/CodeGen/X86/WidenArith.ll | 2 +- test/CodeGen/X86/abi-isel.ll | 1224 +- test/CodeGen/X86/add-of-carry.ll | 6 +- test/CodeGen/X86/add.ll | 34 +- test/CodeGen/X86/aes_intrinsics.ll | 48 + test/CodeGen/X86/alias-error.ll | 5 + test/CodeGen/X86/aliases.ll | 26 +- test/CodeGen/X86/alloca-align-rounding-32.ll | 2 +- test/CodeGen/X86/alloca-align-rounding.ll | 2 +- test/CodeGen/X86/and-su.ll | 4 +- test/CodeGen/X86/anyregcc-crash.ll | 17 + test/CodeGen/X86/anyregcc.ll | 348 + test/CodeGen/X86/apm.ll | 8 +- test/CodeGen/X86/asm-global-imm.ll | 2 +- test/CodeGen/X86/asm-modifier-P.ll | 16 +- test/CodeGen/X86/asm-modifier.ll | 8 +- test/CodeGen/X86/atom-bypass-slow-division-64.ll | 21 +- test/CodeGen/X86/atom-bypass-slow-division.ll | 20 +- test/CodeGen/X86/atom-call-reg-indirect.ll | 14 +- test/CodeGen/X86/atom-lea-addw-bug.ll | 19 + test/CodeGen/X86/atom-lea-sp.ll | 12 +- test/CodeGen/X86/atom-sched.ll | 4 + test/CodeGen/X86/atomic-dagsched.ll | 8 +- test/CodeGen/X86/atomic-minmax-i6432.ll | 2 +- test/CodeGen/X86/atomic-or.ll | 4 +- test/CodeGen/X86/atomic_add.ll | 48 +- test/CodeGen/X86/avx-arith.ll | 5 +- test/CodeGen/X86/avx-basic.ll | 4 +- test/CodeGen/X86/avx-bitcast.ll | 2 +- test/CodeGen/X86/avx-blend.ll | 26 +- test/CodeGen/X86/avx-brcond.ll | 12 +- test/CodeGen/X86/avx-fp2int.ll | 4 +- test/CodeGen/X86/avx-intel-ocl.ll | 13 +- test/CodeGen/X86/avx-minmax.ll | 16 +- test/CodeGen/X86/avx-sext.ll | 11 + test/CodeGen/X86/avx-shift.ll | 3 +- test/CodeGen/X86/avx-shuffle-x86_32.ll | 2 +- test/CodeGen/X86/avx-shuffle.ll | 16 +- test/CodeGen/X86/avx-splat.ll | 2 +- test/CodeGen/X86/avx-trunc.ll | 7 +- test/CodeGen/X86/avx-varargs-x86_64.ll | 2 +- test/CodeGen/X86/avx-vextractf128.ll | 2 +- test/CodeGen/X86/avx-vpermil.ll | 2 +- test/CodeGen/X86/avx-zext.ll | 18 +- test/CodeGen/X86/avx2-arith.ll | 112 +- test/CodeGen/X86/avx2-conversions.ll | 28 + test/CodeGen/X86/avx2-gather.ll | 18 + test/CodeGen/X86/avx2-logic.ll | 4 +- test/CodeGen/X86/avx2-palignr.ll | 18 +- test/CodeGen/X86/avx2-phaddsub.ll | 16 +- test/CodeGen/X86/avx2-shift.ll | 8 +- test/CodeGen/X86/avx2-shuffle.ll | 8 +- test/CodeGen/X86/avx2-vbroadcast.ll | 24 +- test/CodeGen/X86/avx2-vector-shifts.ll | 247 + test/CodeGen/X86/avx512-arith.ll | 271 + test/CodeGen/X86/avx512-build-vector.ll | 18 + test/CodeGen/X86/avx512-cmp.ll | 27 + test/CodeGen/X86/avx512-cvt.ll | 217 + test/CodeGen/X86/avx512-fma-intrinsics.ll | 97 + test/CodeGen/X86/avx512-fma.ll | 83 + test/CodeGen/X86/avx512-gather-scatter-intrin.ll | 225 + test/CodeGen/X86/avx512-insert-extract.ll | 125 + test/CodeGen/X86/avx512-intrinsics.ll | 374 + test/CodeGen/X86/avx512-mask-op.ll | 57 + test/CodeGen/X86/avx512-mov.ll | 155 + test/CodeGen/X86/avx512-select.ll | 22 + test/CodeGen/X86/avx512-shift.ll | 108 + test/CodeGen/X86/avx512-shuffle.ll | 226 + test/CodeGen/X86/avx512-trunc-ext.ll | 127 + test/CodeGen/X86/avx512-vbroadcast.ll | 53 + test/CodeGen/X86/avx512-vec-cmp.ll | 113 + test/CodeGen/X86/bc-extract.ll | 2 +- test/CodeGen/X86/bigstructret2.ll | 10 +- test/CodeGen/X86/bitcast2.ll | 4 +- test/CodeGen/X86/blend-msb.ll | 8 +- test/CodeGen/X86/block-placement.ll | 50 +- test/CodeGen/X86/bmi.ll | 136 +- test/CodeGen/X86/bool-simplify.ll | 2 +- test/CodeGen/X86/brcond.ll | 18 +- test/CodeGen/X86/break-anti-dependencies.ll | 2 +- test/CodeGen/X86/break-avx-dep.ll | 29 + test/CodeGen/X86/break-sse-dep.ll | 12 +- test/CodeGen/X86/bswap-inline-asm.ll | 24 +- test/CodeGen/X86/bswap.ll | 113 +- test/CodeGen/X86/bt.ll | 54 +- test/CodeGen/X86/btq.ll | 4 +- test/CodeGen/X86/byval7.ll | 6 +- test/CodeGen/X86/call-push.ll | 2 +- test/CodeGen/X86/chain_order.ll | 37 + test/CodeGen/X86/change-compare-stride-1.ll | 2 +- .../X86/change-compare-stride-trickiness-0.ll | 2 +- .../X86/change-compare-stride-trickiness-1.ll | 2 +- test/CodeGen/X86/clz.ll | 24 +- test/CodeGen/X86/cmov-fp.ll | 192 +- test/CodeGen/X86/cmov-into-branch.ll | 10 +- test/CodeGen/X86/cmov.ll | 24 +- test/CodeGen/X86/cmp.ll | 27 +- test/CodeGen/X86/coalesce-implicitdef.ll | 35 +- test/CodeGen/X86/coalescer-commute1.ll | 2 +- test/CodeGen/X86/code_placement_align_all.ll | 2 +- test/CodeGen/X86/codegen-prepare.ll | 2 +- test/CodeGen/X86/codemodel.ll | 24 +- test/CodeGen/X86/coff-feat00.ll | 7 + test/CodeGen/X86/commute-two-addr.ll | 14 +- test/CodeGen/X86/compact-unwind.ll | 23 +- test/CodeGen/X86/compare-inf.ll | 114 +- test/CodeGen/X86/compiler_used.ll | 2 +- test/CodeGen/X86/conditional-indecrement.ll | 16 +- test/CodeGen/X86/crash-nosse.ll | 2 +- test/CodeGen/X86/crash.ll | 13 +- test/CodeGen/X86/critical-edge-split-2.ll | 2 +- test/CodeGen/X86/ctpop-combine.ll | 6 +- test/CodeGen/X86/dag-rauw-cse.ll | 2 +- test/CodeGen/X86/dagcombine-buildvector.ll | 4 +- test/CodeGen/X86/dagcombine-shifts.ll | 209 + test/CodeGen/X86/dagcombine-unsafe-math.ll | 56 + test/CodeGen/X86/dagcombine_unsafe_math.ll | 56 - test/CodeGen/X86/dbg-at-specficiation.ll | 20 - test/CodeGen/X86/dbg-byval-parameter.ll | 49 - test/CodeGen/X86/dbg-const-int.ll | 30 - test/CodeGen/X86/dbg-const.ll | 36 - test/CodeGen/X86/dbg-declare-arg.ll | 125 - test/CodeGen/X86/dbg-declare.ll | 55 - test/CodeGen/X86/dbg-file-name.ll | 21 - test/CodeGen/X86/dbg-i128-const.ll | 31 - test/CodeGen/X86/dbg-large-unsigned-const.ll | 58 - test/CodeGen/X86/dbg-merge-loc-entry.ll | 78 - test/CodeGen/X86/dbg-prolog-end.ll | 55 - test/CodeGen/X86/dbg-subrange.ll | 34 - test/CodeGen/X86/dbg-value-dag-combine.ll | 47 - test/CodeGen/X86/dbg-value-isel.ll | 103 - test/CodeGen/X86/dbg-value-location.ll | 74 - test/CodeGen/X86/dbg-value-range.ll | 60 - test/CodeGen/X86/divide-by-constant.ll | 18 +- test/CodeGen/X86/dwarf-comp-dir.ll | 5 +- test/CodeGen/X86/dyn_alloca_aligned.ll | 9 + test/CodeGen/X86/emit-big-cst.ll | 17 + test/CodeGen/X86/extended-fma-contraction.ll | 22 + test/CodeGen/X86/extractelement-load.ll | 4 +- test/CodeGen/X86/fabs.ll | 18 +- test/CodeGen/X86/fast-cc-merge-stack-adj.ll | 2 +- test/CodeGen/X86/fast-cc-pass-in-regs.ll | 8 +- test/CodeGen/X86/fast-isel-call.ll | 8 +- test/CodeGen/X86/fast-isel-divrem-x86-64.ll | 10 +- test/CodeGen/X86/fast-isel-divrem.ll | 28 +- test/CodeGen/X86/fast-isel-extract.ll | 4 +- test/CodeGen/X86/fast-isel-fneg.ll | 4 +- test/CodeGen/X86/fast-isel-gep.ll | 20 +- test/CodeGen/X86/fast-isel-i1.ll | 4 +- test/CodeGen/X86/fast-isel-mem.ll | 6 +- test/CodeGen/X86/fast-isel-ret-ext.ll | 12 +- test/CodeGen/X86/fast-isel-store.ll | 64 + test/CodeGen/X86/fast-isel-tls.ll | 4 +- test/CodeGen/X86/fast-isel-unaligned-store.ll | 18 - test/CodeGen/X86/fast-isel-x86-64.ll | 46 +- test/CodeGen/X86/fast-isel-x86.ll | 10 +- test/CodeGen/X86/fastcc.ll | 4 +- .../CodeGen/X86/fastisel-gep-promote-before-add.ll | 37 + test/CodeGen/X86/floor-soft-float.ll | 13 + test/CodeGen/X86/fma.ll | 8 + test/CodeGen/X86/fma_patterns.ll | 8 +- test/CodeGen/X86/fma_patterns_wide.ll | 84 + test/CodeGen/X86/fold-add.ll | 2 +- test/CodeGen/X86/fold-and-shift.ll | 8 +- test/CodeGen/X86/fold-load-vec.ll | 6 +- test/CodeGen/X86/fold-load.ll | 14 +- test/CodeGen/X86/fold-pcmpeqd-1.ll | 4 +- test/CodeGen/X86/fold-pcmpeqd-2.ll | 17 +- test/CodeGen/X86/force-align-stack-alloca.ll | 2 +- test/CodeGen/X86/fp-elim-and-no-fp-elim.ll | 4 +- test/CodeGen/X86/fp-elim.ll | 70 +- test/CodeGen/X86/fp-fast.ll | 83 +- test/CodeGen/X86/fp-select-cmp-and.ll | 185 + test/CodeGen/X86/fp-une-cmp.ll | 43 + test/CodeGen/X86/fp_constant_op.ll | 24 +- test/CodeGen/X86/frame-base.ll | 22 + test/CodeGen/X86/full-lsr.ll | 2 +- test/CodeGen/X86/gather-addresses.ll | 38 +- test/CodeGen/X86/gcc_except_table.ll | 6 + test/CodeGen/X86/ghc-cc.ll | 7 +- test/CodeGen/X86/ghc-cc64.ll | 31 +- test/CodeGen/X86/global-sections.ll | 8 +- test/CodeGen/X86/h-register-addressing-32.ll | 23 +- test/CodeGen/X86/h-register-addressing-64.ll | 23 +- test/CodeGen/X86/h-registers-0.ll | 42 +- test/CodeGen/X86/h-registers-1.ll | 15 +- test/CodeGen/X86/h-registers-2.ll | 2 +- test/CodeGen/X86/haddsub.ll | 92 +- test/CodeGen/X86/hidden-vis-4.ll | 2 +- test/CodeGen/X86/hidden-vis.ll | 6 +- test/CodeGen/X86/hipe-cc.ll | 6 +- test/CodeGen/X86/hipe-cc64.ll | 12 +- test/CodeGen/X86/hipe-prologue.ll | 12 +- test/CodeGen/X86/hoist-common.ll | 14 +- test/CodeGen/X86/i128-mul.ll | 36 +- test/CodeGen/X86/i128-sdiv.ll | 6 +- test/CodeGen/X86/i486-fence-loop.ll | 27 + test/CodeGen/X86/iabs.ll | 2 +- test/CodeGen/X86/ident-metadata.ll | 9 + test/CodeGen/X86/inline-asm-R-constraint.ll | 2 +- test/CodeGen/X86/inline-asm-error.ll | 2 +- test/CodeGen/X86/inline-asm-flag-clobber.ll | 31 +- test/CodeGen/X86/inline-asm-fpstack.ll | 2 +- test/CodeGen/X86/inreg.ll | 4 +- test/CodeGen/X86/ins_subreg_coalesce-1.ll | 4 +- test/CodeGen/X86/isel-optnone.ll | 42 + test/CodeGen/X86/isel-sink.ll | 2 +- test/CodeGen/X86/jump_sign.ll | 76 +- test/CodeGen/X86/large-gep-chain.ll | 25607 +++++++++++++++++++ test/CodeGen/X86/lea-2.ll | 2 +- test/CodeGen/X86/lea-recursion.ll | 3 +- test/CodeGen/X86/lea.ll | 10 +- test/CodeGen/X86/leaf-fp-elim.ll | 4 +- test/CodeGen/X86/legalize-shift-64.ll | 39 +- test/CodeGen/X86/licm-dominance.ll | 2 +- test/CodeGen/X86/licm-nested.ll | 2 +- test/CodeGen/X86/lit.local.cfg | 8 +- test/CodeGen/X86/load-slice.ll | 139 + test/CodeGen/X86/lock-inst-encoding.ll | 10 +- test/CodeGen/X86/long-extend.ll | 18 + test/CodeGen/X86/longlong-deadload.ll | 2 +- test/CodeGen/X86/loop-blocks.ll | 8 +- test/CodeGen/X86/lsr-interesting-step.ll | 2 +- test/CodeGen/X86/lsr-loop-exit-cond.ll | 15 +- test/CodeGen/X86/lsr-reuse.ll | 22 +- test/CodeGen/X86/lsr-static-addr.ll | 3 +- test/CodeGen/X86/lzcnt.ll | 16 +- test/CodeGen/X86/machine-cp.ll | 4 +- test/CodeGen/X86/machine-cse.ll | 11 +- test/CodeGen/X86/masked-iv-safe.ll | 50 +- test/CodeGen/X86/maskmovdqu.ll | 6 +- test/CodeGen/X86/mcinst-avx-lowering.ll | 4 +- test/CodeGen/X86/mcinst-lowering.ll | 18 + test/CodeGen/X86/memcmp.ll | 14 +- test/CodeGen/X86/memcpy-2.ll | 54 +- test/CodeGen/X86/memcpy.ll | 12 +- test/CodeGen/X86/memset-2.ll | 8 +- test/CodeGen/X86/memset-sse-stack-realignment.ll | 20 +- test/CodeGen/X86/merge_store.ll | 30 + test/CodeGen/X86/mingw-alloca.ll | 25 +- test/CodeGen/X86/misched-balance.ll | 59 +- test/CodeGen/X86/misched-copy.ll | 12 +- test/CodeGen/X86/misched-fusion.ll | 108 + test/CodeGen/X86/misched-matmul.ll | 11 +- test/CodeGen/X86/misched-matrix.ll | 12 +- test/CodeGen/X86/mmx-arg-passing.ll | 21 +- test/CodeGen/X86/mmx-builtins.ll | 12 +- test/CodeGen/X86/mmx-punpckhdq.ll | 2 +- test/CodeGen/X86/mmx-shift.ll | 15 +- test/CodeGen/X86/movbe.ll | 17 +- test/CodeGen/X86/movgs.ll | 20 +- test/CodeGen/X86/movmsk.ll | 6 +- test/CodeGen/X86/ms-inline-asm.ll | 4 +- test/CodeGen/X86/narrow-shl-cst.ll | 22 +- test/CodeGen/X86/narrow-shl-load.ll | 2 +- test/CodeGen/X86/narrow_op-1.ll | 13 +- test/CodeGen/X86/neg_cmp.ll | 2 +- test/CodeGen/X86/neg_fp.ll | 2 +- test/CodeGen/X86/newline-and-quote.ll | 6 + test/CodeGen/X86/no-cmov.ll | 2 +- test/CodeGen/X86/no-compact-unwind.ll | 24 +- test/CodeGen/X86/no-elf-compact-unwind.ll | 48 + test/CodeGen/X86/nocx16.ll | 21 + test/CodeGen/X86/non-lazy-bind.ll | 6 +- test/CodeGen/X86/nonconst-static-ev.ll | 9 + test/CodeGen/X86/nonconst-static-iv.ll | 9 + test/CodeGen/X86/nosse-error1.ll | 2 +- test/CodeGen/X86/nosse-error2.ll | 2 +- test/CodeGen/X86/object-size.ll | 8 +- test/CodeGen/X86/opt-shuff-tstore.ll | 2 +- test/CodeGen/X86/optimize-max-3.ll | 4 +- test/CodeGen/X86/or-address.ll | 2 +- test/CodeGen/X86/palignr-2.ll | 4 +- test/CodeGen/X86/palignr.ll | 20 +- test/CodeGen/X86/pass-three.ll | 2 +- test/CodeGen/X86/patchpoint.ll | 100 + test/CodeGen/X86/peep-setb.ll | 18 +- test/CodeGen/X86/peep-test-3.ll | 8 +- test/CodeGen/X86/peep-test-4.ll | 191 + test/CodeGen/X86/peep-vector-extract-concat.ll | 4 +- test/CodeGen/X86/phaddsub.ll | 56 +- test/CodeGen/X86/phys_subreg_coalesce-3.ll | 2 +- test/CodeGen/X86/pic.ll | 16 +- test/CodeGen/X86/pmovext.ll | 27 +- test/CodeGen/X86/pmovsx-inreg.ll | 51 +- test/CodeGen/X86/pmul.ll | 4 +- test/CodeGen/X86/pmulld.ll | 12 +- test/CodeGen/X86/popcnt.ll | 8 +- test/CodeGen/X86/postra-licm.ll | 4 +- test/CodeGen/X86/pr10523.ll | 2 +- test/CodeGen/X86/pr10524.ll | 2 +- test/CodeGen/X86/pr10525.ll | 2 +- test/CodeGen/X86/pr10526.ll | 2 +- test/CodeGen/X86/pr12312.ll | 2 +- test/CodeGen/X86/pr12360.ll | 8 +- test/CodeGen/X86/pr13209.ll | 2 +- test/CodeGen/X86/pr14088.ll | 15 +- test/CodeGen/X86/pr14090.ll | 10 +- test/CodeGen/X86/pr1505b.ll | 3 +- test/CodeGen/X86/pr16031.ll | 27 + test/CodeGen/X86/pr16360.ll | 16 + test/CodeGen/X86/pr16807.ll | 18 + test/CodeGen/X86/pr17546.ll | 10 + test/CodeGen/X86/pr17631.ll | 34 + test/CodeGen/X86/pr17764.ll | 10 + test/CodeGen/X86/pr18014.ll | 16 + test/CodeGen/X86/pr18023.ll | 31 + test/CodeGen/X86/pr18054.ll | 10 + test/CodeGen/X86/pr18162.ll | 27 + test/CodeGen/X86/pr2182.ll | 2 +- test/CodeGen/X86/pr3216.ll | 2 +- test/CodeGen/X86/pr3457.ll | 2 +- test/CodeGen/X86/pre-ra-sched.ll | 5 +- test/CodeGen/X86/prefetch.ll | 5 + test/CodeGen/X86/prefixdata.ll | 17 + test/CodeGen/X86/private.ll | 16 +- test/CodeGen/X86/promote-i16.ll | 4 +- test/CodeGen/X86/rd-mod-wr-eflags.ll | 2 +- test/CodeGen/X86/rdrand.ll | 18 +- test/CodeGen/X86/rdseed.ll | 14 +- test/CodeGen/X86/red-zone.ll | 4 +- test/CodeGen/X86/red-zone2.ll | 2 +- test/CodeGen/X86/rem-2.ll | 7 - test/CodeGen/X86/rem.ll | 17 +- test/CodeGen/X86/remat-mov-0.ll | 6 +- test/CodeGen/X86/remat-phys-dead.ll | 23 + test/CodeGen/X86/ret-mmx.ll | 8 +- test/CodeGen/X86/returned-trunc-tail-calls.ll | 97 + test/CodeGen/X86/reverse_branches.ll | 2 +- test/CodeGen/X86/rodata-relocs.ll | 37 +- test/CodeGen/X86/rot16.ll | 16 +- test/CodeGen/X86/rot32.ll | 24 +- test/CodeGen/X86/rot64.ll | 8 +- test/CodeGen/X86/rounding-ops.ll | 42 +- test/CodeGen/X86/sandybridge-loads.ll | 2 +- test/CodeGen/X86/scalar_widen_div.ll | 2 +- test/CodeGen/X86/sdiv-exact.ll | 4 +- test/CodeGen/X86/segmented-stacks-dynamic.ll | 8 +- test/CodeGen/X86/segmented-stacks.ll | 38 +- test/CodeGen/X86/select.ll | 96 +- test/CodeGen/X86/select_const.ll | 2 +- test/CodeGen/X86/setcc-narrowing.ll | 18 + test/CodeGen/X86/setcc-sentinals.ll | 13 + test/CodeGen/X86/setcc.ll | 6 +- test/CodeGen/X86/sext-i1.ll | 12 +- test/CodeGen/X86/sext-load.ll | 4 +- test/CodeGen/X86/sext-subreg.ll | 2 +- test/CodeGen/X86/sha.ll | 139 + test/CodeGen/X86/shift-and.ll | 18 +- test/CodeGen/X86/shift-bmi2.ll | 27 +- test/CodeGen/X86/shift-coalesce.ll | 4 +- test/CodeGen/X86/shift-codegen.ll | 4 +- test/CodeGen/X86/shift-combine.ll | 2 +- test/CodeGen/X86/shift-folding.ll | 10 +- test/CodeGen/X86/shl-anyext.ll | 2 +- test/CodeGen/X86/shl_elim.ll | 9 +- test/CodeGen/X86/shrink-compare.ll | 59 +- test/CodeGen/X86/sibcall-2.ll | 16 +- test/CodeGen/X86/sibcall-3.ll | 4 +- test/CodeGen/X86/sibcall-4.ll | 2 +- test/CodeGen/X86/sibcall-5.ll | 8 +- test/CodeGen/X86/sibcall-6.ll | 13 + test/CodeGen/X86/sibcall.ll | 86 +- test/CodeGen/X86/simple-zext.ll | 16 + test/CodeGen/X86/sincos-opt.ll | 14 +- test/CodeGen/X86/sincos.ll | 10 +- test/CodeGen/X86/sink-hoist.ll | 19 +- test/CodeGen/X86/smul-with-overflow.ll | 10 +- test/CodeGen/X86/splat-scalar-load.ll | 2 +- test/CodeGen/X86/sqrt-fastmath.ll | 60 + test/CodeGen/X86/sse-align-12.ll | 8 +- test/CodeGen/X86/sse-align-2.ll | 4 +- test/CodeGen/X86/sse-commute.ll | 2 +- test/CodeGen/X86/sse-intrinsics-x86.ll | 308 + test/CodeGen/X86/sse-minmax.ll | 407 +- test/CodeGen/X86/sse1.ll | 2 +- test/CodeGen/X86/sse2-blend.ll | 2 +- test/CodeGen/X86/sse2-intrinsics-x86.ll | 712 + test/CodeGen/X86/sse2-mul.ll | 2 +- test/CodeGen/X86/sse2-vector-shifts.ll | 247 + test/CodeGen/X86/sse2.ll | 51 +- test/CodeGen/X86/sse3-intrinsics-x86.ll | 57 + test/CodeGen/X86/sse3.ll | 56 +- test/CodeGen/X86/sse41-blend.ll | 16 +- test/CodeGen/X86/sse41-intrinsics-x86.ll | 326 + test/CodeGen/X86/sse41.ll | 16 +- test/CodeGen/X86/sse42-intrinsics-x86.ll | 182 + test/CodeGen/X86/sse42.ll | 4 +- test/CodeGen/X86/sse42_64.ll | 2 +- test/CodeGen/X86/sse4a.ll | 12 +- test/CodeGen/X86/sse_partial_update.ll | 4 +- test/CodeGen/X86/ssse3-intrinsics-x86.ll | 120 + test/CodeGen/X86/stack-align-memcpy.ll | 2 +- test/CodeGen/X86/stack-align.ll | 4 +- test/CodeGen/X86/stack-protector-dbginfo.ll | 97 + .../X86/stack-protector-vreg-to-vreg-copy.ll | 61 + test/CodeGen/X86/stack-protector.ll | 825 +- test/CodeGen/X86/stackmap.ll | 292 + test/CodeGen/X86/stdcall-notailcall.ll | 2 +- test/CodeGen/X86/store-narrow.ll | 56 +- test/CodeGen/X86/store_op_load_fold.ll | 4 +- test/CodeGen/X86/store_op_load_fold2.ll | 8 +- test/CodeGen/X86/sub-with-overflow.ll | 6 +- test/CodeGen/X86/sub.ll | 2 +- test/CodeGen/X86/subtarget-feature-change.ll | 62 - test/CodeGen/X86/switch-bt.ll | 4 +- test/CodeGen/X86/switch-order-weight.ll | 2 +- test/CodeGen/X86/tail-call-attrs.ll | 56 + test/CodeGen/X86/tail-call-got.ll | 4 +- test/CodeGen/X86/tail-call-legality.ll | 32 + test/CodeGen/X86/tail-opts.ll | 22 +- test/CodeGen/X86/tailcall-64.ll | 32 +- test/CodeGen/X86/tailcall-calleesave.ll | 19 + test/CodeGen/X86/tailcall-cgp-dup.ll | 4 +- test/CodeGen/X86/tailcall-disable.ll | 8 +- test/CodeGen/X86/tailcall-largecode.ll | 2 +- test/CodeGen/X86/tailcallbyval64.ll | 2 +- test/CodeGen/X86/tailcallfp2.ll | 2 +- test/CodeGen/X86/tbm-intrinsics-x86_64.ll | 43 + test/CodeGen/X86/tbm_patterns.ll | 253 + test/CodeGen/X86/test-nofold.ll | 9 +- test/CodeGen/X86/test-shrink.ll | 36 +- test/CodeGen/X86/testl-commute.ll | 6 +- test/CodeGen/X86/this-return-64.ll | 12 +- test/CodeGen/X86/tls-local-dynamic.ll | 4 +- test/CodeGen/X86/tls-models.ll | 80 +- test/CodeGen/X86/tls-pic.ll | 20 +- test/CodeGen/X86/tls-pie.ll | 16 +- test/CodeGen/X86/tls.ll | 109 +- test/CodeGen/X86/tlv-1.ll | 4 +- test/CodeGen/X86/tlv-3.ll | 10 + test/CodeGen/X86/trap.ll | 4 +- test/CodeGen/X86/trunc-ext-ld-st.ll | 14 +- test/CodeGen/X86/trunc-to-bool.ll | 12 +- test/CodeGen/X86/twoaddr-lea.ll | 6 +- test/CodeGen/X86/uint_to_fp-2.ll | 2 +- test/CodeGen/X86/umul-with-overflow.ll | 6 +- test/CodeGen/X86/unaligned-spill-folding.ll | 49 + test/CodeGen/X86/unknown-location.ll | 13 +- test/CodeGen/X86/unwind-init.ll | 36 + test/CodeGen/X86/use-add-flags.ll | 6 +- test/CodeGen/X86/v-binop-widen.ll | 3 +- test/CodeGen/X86/v-binop-widen2.ll | 2 +- test/CodeGen/X86/v2f32.ll | 30 +- test/CodeGen/X86/v4i32load-crash.ll | 27 + test/CodeGen/X86/v8i1-masks.ll | 2 +- test/CodeGen/X86/vec-sign.ll | 4 +- test/CodeGen/X86/vec_cast2.ll | 12 +- test/CodeGen/X86/vec_compare-sse4.ll | 16 +- test/CodeGen/X86/vec_compare.ll | 28 +- test/CodeGen/X86/vec_extract-sse4.ll | 2 +- test/CodeGen/X86/vec_extract.ll | 2 +- test/CodeGen/X86/vec_fpext.ll | 2 +- test/CodeGen/X86/vec_insert-2.ll | 14 +- test/CodeGen/X86/vec_insert-3.ll | 2 +- test/CodeGen/X86/vec_insert-5.ll | 44 +- test/CodeGen/X86/vec_insert-7.ll | 2 +- test/CodeGen/X86/vec_insert-8.ll | 2 +- test/CodeGen/X86/vec_insert-9.ll | 2 +- test/CodeGen/X86/vec_insert.ll | 4 +- test/CodeGen/X86/vec_round.ll | 22 + test/CodeGen/X86/vec_sdiv_to_shift.ll | 8 + test/CodeGen/X86/vec_set-8.ll | 4 +- test/CodeGen/X86/vec_set-9.ll | 2 +- test/CodeGen/X86/vec_set-C.ll | 6 +- test/CodeGen/X86/vec_set.ll | 2 +- test/CodeGen/X86/vec_setcc.ll | 187 + test/CodeGen/X86/vec_shift4.ll | 2 +- test/CodeGen/X86/vec_shuffle-14.ll | 38 +- test/CodeGen/X86/vec_shuffle-16.ll | 16 +- test/CodeGen/X86/vec_shuffle-17.ll | 4 +- test/CodeGen/X86/vec_shuffle-25.ll | 2 +- test/CodeGen/X86/vec_shuffle-26.ll | 2 +- test/CodeGen/X86/vec_shuffle-27.ll | 6 +- test/CodeGen/X86/vec_shuffle-36.ll | 2 +- test/CodeGen/X86/vec_shuffle-39.ll | 18 +- test/CodeGen/X86/vec_splat-2.ll | 2 +- test/CodeGen/X86/vec_splat-3.ll | 50 +- test/CodeGen/X86/vec_splat.ll | 8 +- test/CodeGen/X86/vec_split.ll | 42 + test/CodeGen/X86/vec_ss_load_fold.ll | 12 +- test/CodeGen/X86/vec_uint_to_fp.ll | 2 +- test/CodeGen/X86/vector-gep.ll | 14 +- test/CodeGen/X86/vector-variable-idx2.ll | 2 +- test/CodeGen/X86/viabs.ll | 50 +- test/CodeGen/X86/vselect-minmax.ll | 384 +- test/CodeGen/X86/vshift-1.ll | 24 +- test/CodeGen/X86/vshift-2.ll | 24 +- test/CodeGen/X86/vshift-3.ll | 22 +- test/CodeGen/X86/vshift-4.ll | 26 +- test/CodeGen/X86/vshift-5.ll | 8 +- test/CodeGen/X86/vsplit-and.ll | 2 +- test/CodeGen/X86/warn-stack.ll | 24 + test/CodeGen/X86/weak_def_can_be_hidden.ll | 26 + test/CodeGen/X86/wide-fma-contraction.ll | 19 +- test/CodeGen/X86/widen_arith-1.ll | 2 +- test/CodeGen/X86/widen_arith-2.ll | 2 +- test/CodeGen/X86/widen_arith-3.ll | 6 +- test/CodeGen/X86/widen_arith-4.ll | 4 +- test/CodeGen/X86/widen_arith-5.ll | 4 +- test/CodeGen/X86/widen_arith-6.ll | 2 +- test/CodeGen/X86/widen_cast-1.ll | 4 +- test/CodeGen/X86/widen_cast-2.ll | 2 +- test/CodeGen/X86/widen_cast-3.ll | 2 +- test/CodeGen/X86/widen_cast-4.ll | 2 +- test/CodeGen/X86/widen_cast-5.ll | 2 +- test/CodeGen/X86/widen_cast-6.ll | 2 +- test/CodeGen/X86/widen_conv-1.ll | 2 +- test/CodeGen/X86/widen_conv-2.ll | 6 +- test/CodeGen/X86/widen_conv-3.ll | 2 +- test/CodeGen/X86/widen_conv-4.ll | 2 +- test/CodeGen/X86/widen_extract-1.ll | 4 +- test/CodeGen/X86/widen_load-1.ll | 4 +- test/CodeGen/X86/widen_load-2.ll | 14 +- test/CodeGen/X86/widen_shuffle-1.ll | 12 +- test/CodeGen/X86/win32_sret.ll | 4 +- test/CodeGen/X86/win64_alloca_dynalloca.ll | 66 +- test/CodeGen/X86/win64_params.ll | 25 + test/CodeGen/X86/win64_vararg.ll | 66 +- test/CodeGen/X86/win_chkstk.ll | 13 + test/CodeGen/X86/x86-64-and-mask.ll | 12 +- test/CodeGen/X86/x86-64-pic-10.ll | 4 +- test/CodeGen/X86/x86-64-psub.ll | 220 + test/CodeGen/X86/x86-64-sret-return.ll | 8 +- test/CodeGen/X86/x86-64-tls-1.ll | 6 +- test/CodeGen/X86/x86-shifts.ll | 12 +- test/CodeGen/X86/xmulo.ll | 6 +- test/CodeGen/X86/xor-icmp.ll | 8 +- test/CodeGen/X86/xor.ll | 67 +- test/CodeGen/X86/zero-remat.ll | 8 +- test/CodeGen/X86/zext-extract_subreg.ll | 4 +- test/CodeGen/X86/zext-fold.ll | 6 +- test/CodeGen/X86/zext-sext.ll | 17 +- test/CodeGen/X86/zext-shl.ll | 4 +- test/CodeGen/X86/zext-trunc.ll | 2 +- test/CodeGen/XCore/2011-08-01-DynamicAllocBug.ll | 2 +- test/CodeGen/XCore/2011-08-01-VarargsBug.ll | 17 - test/CodeGen/XCore/addsub64.ll | 6 +- test/CodeGen/XCore/aliases.ll | 14 +- test/CodeGen/XCore/alignment.ll | 9 + test/CodeGen/XCore/ashr.ll | 32 +- test/CodeGen/XCore/atomic.ll | 16 + test/CodeGen/XCore/bigstructret.ll | 4 +- test/CodeGen/XCore/byVal.ll | 73 + test/CodeGen/XCore/constants.ll | 10 +- test/CodeGen/XCore/epilogue_prologue.ll | 26 + test/CodeGen/XCore/events.ll | 4 +- test/CodeGen/XCore/exception.ll | 129 + test/CodeGen/XCore/float-intrinsics.ll | 40 +- test/CodeGen/XCore/fneg.ll | 2 +- test/CodeGen/XCore/getid.ll | 2 +- test/CodeGen/XCore/globals.ll | 20 +- test/CodeGen/XCore/indirectbr.ll | 2 +- test/CodeGen/XCore/inline-asm.ll | 32 + test/CodeGen/XCore/ladd_lsub_combine.ll | 10 +- test/CodeGen/XCore/licm-ldwcp.ll | 2 +- test/CodeGen/XCore/linkage.ll | 38 + test/CodeGen/XCore/lit.local.cfg | 2 - test/CodeGen/XCore/load.ll | 17 +- test/CodeGen/XCore/misc-intrinsics.ll | 18 +- test/CodeGen/XCore/mkmsk.ll | 2 +- test/CodeGen/XCore/mul64.ll | 8 +- test/CodeGen/XCore/offset_folding.ll | 8 +- test/CodeGen/XCore/private.ll | 2 +- test/CodeGen/XCore/ps-intrinsics.ll | 4 +- test/CodeGen/XCore/resources.ll | 54 +- test/CodeGen/XCore/sext.ll | 8 +- test/CodeGen/XCore/shedulingPreference.ll | 25 + test/CodeGen/XCore/sr-intrinsics.ll | 4 +- test/CodeGen/XCore/store.ll | 8 +- test/CodeGen/XCore/threads.ll | 142 +- test/CodeGen/XCore/tls.ll | 2 +- test/CodeGen/XCore/trampoline.ll | 2 +- test/CodeGen/XCore/trap.ll | 2 +- test/CodeGen/XCore/unaligned_load.ll | 4 +- test/CodeGen/XCore/unaligned_store.ll | 2 +- test/CodeGen/XCore/unaligned_store_combine.ll | 2 +- test/CodeGen/XCore/varargs.ll | 55 + test/CodeGen/XCore/zext.ll | 10 + test/CodeGen/XCore/zextfree.ll | 15 + test/DebugInfo/2009-11-03-InsertExtractValue.ll | 15 +- test/DebugInfo/2009-11-05-DeadGlobalVariable.ll | 20 +- .../DebugInfo/2009-11-06-NamelessGlobalVariable.ll | 15 +- test/DebugInfo/2009-11-10-CurrentFn.ll | 21 +- test/DebugInfo/2010-01-05-DbgScope.ll | 17 +- test/DebugInfo/2010-01-19-DbgScope.ll | 23 +- test/DebugInfo/2010-03-12-llc-crash.ll | 16 +- test/DebugInfo/2010-03-19-DbgDeclare.ll | 2 + test/DebugInfo/2010-03-24-MemberFn.ll | 21 +- test/DebugInfo/2010-03-30-InvalidDbgInfoCrash.ll | 30 +- test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll | 36 +- test/DebugInfo/2010-04-19-FramePtr.ll | 20 +- test/DebugInfo/2010-05-03-DisableFramePtr.ll | 34 +- test/DebugInfo/2010-05-03-OriginDIE.ll | 48 +- test/DebugInfo/2010-05-10-MultipleCU.ll | 29 +- test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll | 18 +- test/DebugInfo/2010-07-19-Crash.ll | 24 +- test/DebugInfo/2010-10-01-crash.ll | 14 +- test/DebugInfo/AArch64/dwarfdump.ll | 8 +- test/DebugInfo/AArch64/lit.local.cfg | 2 - test/DebugInfo/AArch64/variable-loc.ll | 39 +- test/DebugInfo/ARM/PR16736.ll | 65 + test/DebugInfo/ARM/lit.local.cfg | 4 + test/DebugInfo/ARM/lowerbdgdeclare_vla.ll | 103 + test/DebugInfo/ARM/selectiondag-deadcode.ll | 27 + test/DebugInfo/Inputs/dwarfdump-inl-test.cc | 3 + .../Inputs/dwarfdump-inl-test.high_pc.elf-x86-64 | Bin 0 -> 7422 bytes .../Inputs/dwarfdump-test-loc-list-32bit.elf.cpp | 13 + .../Inputs/dwarfdump-test-loc-list-32bit.elf.o | Bin 0 -> 2604 bytes .../Inputs/dwarfdump-test.elf-x86-64.debuglink | Bin 0 -> 8668 bytes test/DebugInfo/Inputs/dwarfdump-type-units.cc | 15 + .../Inputs/dwarfdump-type-units.elf-x86-64 | Bin 0 -> 3928 bytes test/DebugInfo/Inputs/lit.local.cfg | 1 - test/DebugInfo/Inputs/macho-universal | Bin 0 -> 16660 bytes test/DebugInfo/Inputs/macho-universal.cc | 10 + test/DebugInfo/PowerPC/lit.local.cfg | 3 + test/DebugInfo/PowerPC/tls-fission.ll | 32 + test/DebugInfo/PowerPC/tls.ll | 29 + test/DebugInfo/SystemZ/lit.local.cfg | 2 - test/DebugInfo/SystemZ/variable-loc.ll | 26 +- test/DebugInfo/X86/2010-04-13-PubType.ll | 17 +- test/DebugInfo/X86/2010-08-10-DbgConstant.ll | 18 +- test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll | 14 +- test/DebugInfo/X86/2011-12-16-BadStructRef.ll | 38 +- test/DebugInfo/X86/DW_AT_byte_size.ll | 13 +- test/DebugInfo/X86/DW_AT_location-reference.ll | 12 +- test/DebugInfo/X86/DW_AT_object_pointer.ll | 18 +- test/DebugInfo/X86/DW_AT_specification.ll | 16 +- test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll | 41 + test/DebugInfo/X86/DW_TAG_friend.ll | 22 +- test/DebugInfo/X86/aligned_stack_var.ll | 15 +- test/DebugInfo/X86/arguments.ll | 73 + test/DebugInfo/X86/block-capture.ll | 25 +- test/DebugInfo/X86/byvalstruct.ll | 127 + test/DebugInfo/X86/coff_relative_names.ll | 41 + test/DebugInfo/X86/concrete_out_of_line.ll | 36 +- test/DebugInfo/X86/data_member_location.ll | 44 + test/DebugInfo/X86/dbg-at-specficiation.ll | 21 + test/DebugInfo/X86/dbg-byval-parameter.ll | 52 + test/DebugInfo/X86/dbg-const-int.ll | 37 + test/DebugInfo/X86/dbg-const.ll | 51 + test/DebugInfo/X86/dbg-declare-arg.ll | 127 + test/DebugInfo/X86/dbg-declare.ll | 58 + test/DebugInfo/X86/dbg-file-name.ll | 24 + test/DebugInfo/X86/dbg-i128-const.ll | 34 + test/DebugInfo/X86/dbg-large-unsigned-const.ll | 62 + test/DebugInfo/X86/dbg-merge-loc-entry.ll | 75 + test/DebugInfo/X86/dbg-prolog-end.ll | 59 + test/DebugInfo/X86/dbg-subrange.ll | 37 + test/DebugInfo/X86/dbg-value-dag-combine.ll | 49 + test/DebugInfo/X86/dbg-value-inlined-parameter.ll | 19 +- test/DebugInfo/X86/dbg-value-isel.ll | 106 + test/DebugInfo/X86/dbg-value-location.ll | 77 + test/DebugInfo/X86/dbg-value-range.ll | 63 + test/DebugInfo/X86/dbg-value-terminator.ll | 133 + test/DebugInfo/X86/dbg_value_direct.ll | 177 + .../X86/debug-info-block-captured-self.ll | 14 +- test/DebugInfo/X86/debug-info-blocks.ll | 47 +- test/DebugInfo/X86/debug-info-static-member.ll | 17 +- test/DebugInfo/X86/debug_frame.ll | 11 +- .../DebugInfo/X86/dwarf-aranges-no-dwarf-labels.ll | 89 + test/DebugInfo/X86/dwarf-aranges.ll | 87 + test/DebugInfo/X86/dwarf-public-names.ll | 132 + test/DebugInfo/X86/dwarf-pubnames-split.ll | 38 + test/DebugInfo/X86/earlydup-crash.ll | 85 +- test/DebugInfo/X86/eh_symbol.ll | 16 +- test/DebugInfo/X86/elf-names.ll | 25 +- test/DebugInfo/X86/empty-and-one-elem-array.ll | 56 +- test/DebugInfo/X86/empty-array.ll | 34 +- test/DebugInfo/X86/ending-run.ll | 8 +- test/DebugInfo/X86/enum-class.ll | 20 +- test/DebugInfo/X86/enum-fwd-decl.ll | 9 +- test/DebugInfo/X86/fission-cu.ll | 24 +- test/DebugInfo/X86/fission-hash.ll | 16 + test/DebugInfo/X86/fission-ranges.ll | 151 + test/DebugInfo/X86/generate-odr-hash.ll | 196 + test/DebugInfo/X86/gnu-public-names-empty.ll | 19 + test/DebugInfo/X86/gnu-public-names.ll | 219 + test/DebugInfo/X86/instcombine-instrinsics.ll | 12 +- test/DebugInfo/X86/line-info.ll | 6 +- test/DebugInfo/X86/linkage-name.ll | 14 +- test/DebugInfo/X86/lit.local.cfg | 2 - test/DebugInfo/X86/low-pc-cu.ll | 15 +- test/DebugInfo/X86/misched-dbg-value.ll | 22 +- test/DebugInfo/X86/multiple-aranges.ll | 66 + test/DebugInfo/X86/multiple-at-const-val.ll | 16 +- test/DebugInfo/X86/nondefault-subrange-array.ll | 38 +- test/DebugInfo/X86/objc-fwd-decl.ll | 11 +- test/DebugInfo/X86/op_deref.ll | 29 +- test/DebugInfo/X86/parameters.ll | 116 + test/DebugInfo/X86/pointer-type-size.ll | 6 +- test/DebugInfo/X86/pr11300.ll | 21 +- test/DebugInfo/X86/pr12831.ll | 126 +- test/DebugInfo/X86/pr13303.ll | 15 +- test/DebugInfo/X86/pr9951.ll | 15 +- test/DebugInfo/X86/prologue-stack.ll | 15 +- test/DebugInfo/X86/ref_addr_relocation.ll | 71 + test/DebugInfo/X86/reference-argument.ll | 103 + test/DebugInfo/X86/rvalue-ref.ll | 12 +- .../X86/stmt-list-multiple-compile-units.ll | 13 +- test/DebugInfo/X86/stmt-list.ll | 11 +- test/DebugInfo/X86/stringpool.ll | 26 +- test/DebugInfo/X86/struct-loc.ll | 8 +- test/DebugInfo/X86/subrange-type.ll | 12 +- test/DebugInfo/X86/subreg.ll | 15 +- test/DebugInfo/X86/template.ll | 126 + test/DebugInfo/X86/tls-fission.ll | 32 + test/DebugInfo/X86/tls.ll | 35 + test/DebugInfo/X86/union-template.ll | 10 +- test/DebugInfo/X86/vector.ll | 6 +- test/DebugInfo/X86/vla.ll | 107 + test/DebugInfo/array.ll | 15 +- test/DebugInfo/bug_null_debuginfo.ll | 5 +- test/DebugInfo/debuginfofinder-multiple-cu.ll | 41 + test/DebugInfo/dwarf-public-names.ll | 17 +- test/DebugInfo/dwarfdump-debug-loc-simple.test | 26 + test/DebugInfo/dwarfdump-pubnames.test | 20 +- test/DebugInfo/dwarfdump-type-units.test | 32 + test/DebugInfo/enum.ll | 80 + test/DebugInfo/global.ll | 39 + test/DebugInfo/inheritance.ll | 53 +- test/DebugInfo/inline-debug-info-multiret.ll | 6 +- test/DebugInfo/inline-debug-info.ll | 6 +- test/DebugInfo/inlined-arguments.ll | 77 + test/DebugInfo/inlined-vars.ll | 12 +- test/DebugInfo/lit.local.cfg | 1 - test/DebugInfo/llvm-symbolizer.test | 40 +- test/DebugInfo/member-order.ll | 66 + test/DebugInfo/member-pointers.ll | 16 +- test/DebugInfo/namespace.ll | 220 +- test/DebugInfo/template-recursive-void.ll | 65 + test/DebugInfo/tu-composite.ll | 185 + test/DebugInfo/tu-member-pointer.ll | 30 + test/DebugInfo/two-cus-from-same-file.ll | 22 +- test/DebugInfo/version.ll | 32 + .../ExecutionEngine/MCJIT/Inputs/cross-module-b.ll | 7 + .../ExecutionEngine/MCJIT/Inputs/multi-module-b.ll | 7 + .../ExecutionEngine/MCJIT/Inputs/multi-module-c.ll | 4 + .../MCJIT/Inputs/multi-module-eh-b.ll | 30 + test/ExecutionEngine/MCJIT/cross-module-a.ll | 13 + .../ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll | 14 + test/ExecutionEngine/MCJIT/eh-lg-pic.ll | 32 + test/ExecutionEngine/MCJIT/eh-sm-pic.ll | 32 + test/ExecutionEngine/MCJIT/hello-sm-pic.ll | 12 + test/ExecutionEngine/MCJIT/lit.local.cfg | 23 +- test/ExecutionEngine/MCJIT/multi-module-a.ll | 9 + test/ExecutionEngine/MCJIT/multi-module-eh-a.ll | 35 + .../ExecutionEngine/MCJIT/multi-module-sm-pic-a.ll | 10 + .../MCJIT/remote/Inputs/cross-module-b.ll | 7 + .../MCJIT/remote/Inputs/multi-module-b.ll | 7 + .../MCJIT/remote/Inputs/multi-module-c.ll | 4 + .../ExecutionEngine/MCJIT/remote/cross-module-a.ll | 13 + .../MCJIT/remote/cross-module-sm-pic-a.ll | 14 + test/ExecutionEngine/MCJIT/remote/lit.local.cfg | 3 + .../ExecutionEngine/MCJIT/remote/multi-module-a.ll | 9 + .../MCJIT/remote/multi-module-sm-pic-a.ll | 10 + .../MCJIT/remote/simpletest-remote.ll | 10 + test/ExecutionEngine/MCJIT/remote/stubs-remote.ll | 37 + test/ExecutionEngine/MCJIT/remote/stubs-sm-pic.ll | 37 + .../MCJIT/remote/test-common-symbols-remote.ll | 88 + .../MCJIT/remote/test-data-align-remote.ll | 15 + .../remote/test-fp-no-external-funcs-remote.ll | 20 + .../remote/test-global-init-nonzero-remote.ll | 34 + .../remote/test-global-init-nonzero-sm-pic.ll | 35 + .../MCJIT/remote/test-ptr-reloc-remote.ll | 15 + .../MCJIT/remote/test-ptr-reloc-sm-pic.ll | 17 + test/ExecutionEngine/MCJIT/simpletest-remote.ll | 12 - test/ExecutionEngine/MCJIT/stubs-remote.ll | 36 - test/ExecutionEngine/MCJIT/stubs-sm-pic.ll | 36 + .../MCJIT/test-common-symbols-remote.ll | 89 - .../MCJIT/test-data-align-remote.ll | 16 - .../MCJIT/test-fp-no-external-funcs-remote.ll | 22 - .../MCJIT/test-global-init-nonzero-remote.ll | 35 - .../MCJIT/test-global-init-nonzero-sm-pic.ll | 35 + .../ExecutionEngine/MCJIT/test-ptr-reloc-remote.ll | 17 - .../ExecutionEngine/MCJIT/test-ptr-reloc-sm-pic.ll | 17 + .../RuntimeDyld/Inputs/arm_secdiff_reloc.o | Bin 0 -> 616 bytes .../RuntimeDyld/arm_secdiff_reloc.test | 1 + test/ExecutionEngine/fma3-jit.ll | 18 + test/ExecutionEngine/lit.local.cfg | 15 +- test/ExecutionEngine/mov64zext32.ll | 18 + test/ExecutionEngine/test-interp-vec-cast.ll | 146 + .../test-interp-vec-insertelement.ll | 41 + .../test-interp-vec-insertextractvalue.ll | 21 + test/ExecutionEngine/test-interp-vec-loadstore.ll | 190 +- test/ExecutionEngine/test-interp-vec-select.ll | 118 + test/ExecutionEngine/test-interp-vec-shift.ll | 32 + test/ExecutionEngine/test-interp-vec-shuffle.ll | 81 + test/Feature/cold.ll | 9 + test/Feature/lit.local.cfg | 1 - test/Feature/md_on_instruction.ll | 9 +- test/Feature/newcasts.ll | 3 + test/Feature/optnone.ll | 12 + test/Feature/prefixdata.ll | 18 + test/FileCheck/check-a-b-has-b.txt | 5 + test/FileCheck/check-b-a-has-b.txt | 5 + test/FileCheck/check-dag-multi-prefix-2.txt | 7 + test/FileCheck/check-dag-multi-prefix.txt | 27 + test/FileCheck/check-dag-substring-prefix.txt | 7 + test/FileCheck/check-dag-xfails.txt | 85 + test/FileCheck/check-dag.txt | 26 + test/FileCheck/check-label-dag-capture.txt | 11 + test/FileCheck/check-label-dag.txt | 11 + test/FileCheck/check-label.txt | 51 + test/FileCheck/check-multi-prefix-label.txt | 6 + test/FileCheck/check-multiple-prefixes-mixed.txt | 10 + test/FileCheck/check-multiple-prefixes-nomatch.txt | 10 + test/FileCheck/check-multiple-prefixes-substr.txt | 5 + test/FileCheck/check-not-diaginfo.txt | 2 +- test/FileCheck/check-prefixes.txt | 9 + test/FileCheck/check-substring-multi-prefix-2.txt | 11 + test/FileCheck/check-substring-multi-prefix.txt | 9 + test/FileCheck/first-character-match.txt | 2 + test/FileCheck/line-count-2.txt | 11 + test/FileCheck/line-count.txt | 15 + test/FileCheck/lit.local.cfg | 1 - test/FileCheck/multiple-missing-prefixes.txt | 9 + test/FileCheck/separate-multi-prefix.txt | 7 + test/FileCheck/validate-check-prefix.txt | 9 + .../AddressSanitizer/X86/bug_11395.ll | 6 +- .../AddressSanitizer/X86/lit.local.cfg | 11 +- .../AddressSanitizer/asan-vs-gvn.ll | 2 +- test/Instrumentation/AddressSanitizer/basic.ll | 19 + test/Instrumentation/AddressSanitizer/coverage.ll | 13 + .../Instrumentation/AddressSanitizer/debug_info.ll | 18 +- .../do-not-instrument-internal-globals.ll | 4 +- .../AddressSanitizer/instrument_global.ll | 65 +- .../keep-instrumented_functions.ll | 23 + .../AddressSanitizer/lifetime-uar.ll | 33 + test/Instrumentation/AddressSanitizer/lifetime.ll | 6 +- .../Instrumentation/AddressSanitizer/lit.local.cfg | 1 - test/Instrumentation/BoundsChecking/lit.local.cfg | 1 - test/Instrumentation/BoundsChecking/simple-32.ll | 29 + test/Instrumentation/BoundsChecking/simple.ll | 17 + .../DataFlowSanitizer/Inputs/abilist.txt | 8 + test/Instrumentation/DataFlowSanitizer/abilist.ll | 75 + .../DataFlowSanitizer/args-unreachable-bb.ll | 30 + test/Instrumentation/DataFlowSanitizer/arith.ll | 63 + test/Instrumentation/DataFlowSanitizer/call.ll | 23 + .../DataFlowSanitizer/debug-nonzero-labels.ll | 23 + test/Instrumentation/DataFlowSanitizer/load.ll | 81 + test/Instrumentation/DataFlowSanitizer/memset.ll | 11 + .../DataFlowSanitizer/prefix-rename.ll | 14 + test/Instrumentation/DataFlowSanitizer/store.ll | 75 + test/Instrumentation/MemorySanitizer/X86/vararg.ll | 15 + test/Instrumentation/MemorySanitizer/atomics.ll | 189 + test/Instrumentation/MemorySanitizer/lit.local.cfg | 1 - test/Instrumentation/MemorySanitizer/msan_basic.ll | 190 +- .../MemorySanitizer/return_from_main.ll | 18 + test/Instrumentation/MemorySanitizer/vector_cvt.ll | 66 + .../MemorySanitizer/wrap_indirect_calls.ll | 34 + test/Instrumentation/ThreadSanitizer/lit.local.cfg | 1 - .../ThreadSanitizer/no_sanitize_thread.ll | 36 + .../ThreadSanitizer/read_before_write.ll | 4 +- .../ThreadSanitizer/read_from_global.ll | 18 +- test/Instrumentation/ThreadSanitizer/tsan_basic.ll | 4 +- test/Instrumentation/ThreadSanitizer/vptr_read.ll | 6 +- .../Instrumentation/ThreadSanitizer/vptr_update.ll | 6 +- test/Integer/lit.local.cfg | 1 - test/JitListener/lit.local.cfg | 10 +- test/JitListener/test-common-symbols.ll | 38 +- test/JitListener/test-inline.ll | 64 +- test/JitListener/test-parameters.ll | 64 +- test/LTO/cfi_endproc.ll | 37 + test/LTO/linkonce_odr_func.ll | 45 + test/LTO/lit.local.cfg | 3 + test/LTO/runtime-library.ll | 27 + test/Linker/2011-08-04-DebugLoc.ll | 17 +- test/Linker/2011-08-04-DebugLoc2.ll | 17 +- test/Linker/2011-08-04-Metadata.ll | 16 +- test/Linker/2011-08-04-Metadata2.ll | 16 +- test/Linker/2011-08-18-unique-class-type.ll | 23 +- test/Linker/2011-08-18-unique-class-type2.ll | 23 +- test/Linker/2011-08-18-unique-debug-type.ll | 19 +- test/Linker/2011-08-18-unique-debug-type2.ll | 18 +- test/Linker/DbgDeclare.ll | 26 +- test/Linker/DbgDeclare2.ll | 31 +- test/Linker/Inputs/type-unique-inheritance-a.ll | 94 + test/Linker/Inputs/type-unique-inheritance-b.ll | 81 + test/Linker/Inputs/type-unique-simple2-a.ll | 88 + test/Linker/Inputs/type-unique-simple2-b.ll | 67 + test/Linker/lit.local.cfg | 1 - test/Linker/prefixdata.ll | 9 + test/Linker/transitive-lazy-link.ll | 20 + test/Linker/type-unique-inheritance.ll | 1 + test/Linker/type-unique-simple-a.ll | 91 + test/Linker/type-unique-simple-b.ll | 67 + test/Linker/type-unique-simple2.ll | 6 + test/Linker/unnamed-addr-err-a.ll | 4 + test/Linker/unnamed-addr-err-b.ll | 4 + test/Linker/unnamed-addr1-a.ll | 61 +- test/Linker/unnamed-addr1-b.ll | 26 +- test/MC/AArch64/adrp-relocation.s | 18 + test/MC/AArch64/basic-a64-diagnostics.s | 8 +- test/MC/AArch64/basic-a64-instructions.s | 2 +- test/MC/AArch64/basic-pic.s | 98 + test/MC/AArch64/elf-extern.s | 33 + test/MC/AArch64/elf-globaladdress.ll | 2 +- test/MC/AArch64/elf-objdump.s | 2 +- test/MC/AArch64/elf-reloc-addend.s | 8 + test/MC/AArch64/elf-reloc-addsubimm.s | 2 +- test/MC/AArch64/elf-reloc-condbr.s | 2 +- test/MC/AArch64/elf-reloc-ldrlit.s | 2 +- test/MC/AArch64/elf-reloc-ldstunsimm.s | 4 +- test/MC/AArch64/elf-reloc-movw.s | 2 +- test/MC/AArch64/elf-reloc-pcreladdressing.s | 2 +- test/MC/AArch64/elf-reloc-tstb.s | 2 +- test/MC/AArch64/elf-reloc-uncondbrimm.s | 2 +- test/MC/AArch64/gicv3-regs-diagnostics.s | 2 +- test/MC/AArch64/inline-asm-modifiers.s | 209 + test/MC/AArch64/jump-table.s | 59 + test/MC/AArch64/lit.local.cfg | 2 - test/MC/AArch64/neon-2velem.s | 271 + test/MC/AArch64/neon-3vdiff.s | 415 + test/MC/AArch64/neon-aba-abd.s | 78 + test/MC/AArch64/neon-across.s | 101 + test/MC/AArch64/neon-add-pairwise.s | 34 + test/MC/AArch64/neon-add-sub-instructions.s | 68 + test/MC/AArch64/neon-bitwise-instructions.s | 60 + test/MC/AArch64/neon-compare-instructions.s | 405 + test/MC/AArch64/neon-crypto.s | 44 + test/MC/AArch64/neon-diagnostics.s | 7318 ++++++ test/MC/AArch64/neon-extract.s | 13 + test/MC/AArch64/neon-facge-facgt.s | 41 + test/MC/AArch64/neon-frsqrt-frecp.s | 27 + test/MC/AArch64/neon-halving-add-sub.s | 74 + test/MC/AArch64/neon-max-min-pairwise.s | 110 + test/MC/AArch64/neon-max-min.s | 110 + test/MC/AArch64/neon-mla-mls-instructions.s | 61 + test/MC/AArch64/neon-mov.s | 209 + test/MC/AArch64/neon-mul-div-instructions.s | 86 + test/MC/AArch64/neon-perm.s | 103 + test/MC/AArch64/neon-rounding-halving-add.s | 39 + test/MC/AArch64/neon-rounding-shift.s | 45 + test/MC/AArch64/neon-saturating-add-sub.s | 82 + test/MC/AArch64/neon-saturating-rounding-shift.s | 43 + test/MC/AArch64/neon-saturating-shift.s | 43 + test/MC/AArch64/neon-scalar-abs.s | 35 + test/MC/AArch64/neon-scalar-add-sub.s | 16 + test/MC/AArch64/neon-scalar-by-elem-mla.s | 44 + test/MC/AArch64/neon-scalar-by-elem-mul.s | 37 + .../AArch64/neon-scalar-by-elem-saturating-mla.s | 46 + .../AArch64/neon-scalar-by-elem-saturating-mul.s | 58 + test/MC/AArch64/neon-scalar-compare.s | 90 + test/MC/AArch64/neon-scalar-cvt.s | 181 + test/MC/AArch64/neon-scalar-dup.s | 55 + test/MC/AArch64/neon-scalar-extract-narrow.s | 40 + test/MC/AArch64/neon-scalar-fp-compare.s | 103 + test/MC/AArch64/neon-scalar-mul.s | 63 + test/MC/AArch64/neon-scalar-neg.s | 25 + test/MC/AArch64/neon-scalar-recip.s | 53 + test/MC/AArch64/neon-scalar-reduce-pairwise.s | 16 + test/MC/AArch64/neon-scalar-rounding-shift.s | 17 + test/MC/AArch64/neon-scalar-saturating-add-sub.s | 81 + .../neon-scalar-saturating-rounding-shift.s | 28 + test/MC/AArch64/neon-scalar-saturating-shift.s | 29 + test/MC/AArch64/neon-scalar-shift-imm.s | 186 + test/MC/AArch64/neon-scalar-shift.s | 16 + test/MC/AArch64/neon-shift-left-long.s | 37 + test/MC/AArch64/neon-shift.s | 61 + test/MC/AArch64/neon-simd-copy.s | 135 + test/MC/AArch64/neon-simd-ldst-multi-elem.s | 463 + test/MC/AArch64/neon-simd-ldst-one-elem.s | 325 + test/MC/AArch64/neon-simd-misc.s | 646 + test/MC/AArch64/neon-simd-post-ldst-multi-elem.s | 389 + test/MC/AArch64/neon-simd-shift.s | 434 + test/MC/AArch64/neon-tbl.s | 56 + test/MC/AArch64/noneon-diagnostics.s | 28 + test/MC/AArch64/tls-relocs.s | 8 +- test/MC/AArch64/trace-regs-diagnostics.s | 2 +- test/MC/ARM/2010-11-30-reloc-movt.s | 41 + test/MC/ARM/AlignedBundling/lit.local.cfg | 2 - test/MC/ARM/align_arm_2_thumb.s | 15 + test/MC/ARM/align_thumb_2_arm.s | 15 + test/MC/ARM/arm-ldrd.s | 57 + test/MC/ARM/arm-memory-instructions.s | 45 +- test/MC/ARM/arm-thumb-cpus-default.s | 13 + test/MC/ARM/arm-thumb-cpus.s | 20 + test/MC/ARM/arm-thumb-trustzone.s | 2 +- test/MC/ARM/arm-trustzone.s | 2 +- test/MC/ARM/basic-arm-instructions-v8.s | 59 + test/MC/ARM/basic-arm-instructions.s | 111 +- test/MC/ARM/basic-thumb-instructions.s | 22 +- test/MC/ARM/basic-thumb2-instructions-v8.s | 87 + test/MC/ARM/basic-thumb2-instructions.s | 220 +- test/MC/ARM/crc32-thumb.s | 30 + test/MC/ARM/crc32.s | 30 + test/MC/ARM/data-in-code.ll | 14 +- test/MC/ARM/deprecated-v8.s | 51 + test/MC/ARM/diagnostics-noneon.s | 7 + test/MC/ARM/diagnostics.s | 94 + test/MC/ARM/directive-cpu.s | 26 + test/MC/ARM/directive-eabi_attribute.s | 56 + test/MC/ARM/directive-fpu-multiple.s | 26 + test/MC/ARM/directive-fpu.s | 26 + test/MC/ARM/eh-compact-pr0.s | 104 + test/MC/ARM/eh-compact-pr1.s | 74 + test/MC/ARM/eh-directive-cantunwind-diagnostics.s | 106 + test/MC/ARM/eh-directive-cantunwind.s | 51 + test/MC/ARM/eh-directive-fnend-diagnostics.s | 17 + test/MC/ARM/eh-directive-fnstart-diagnostics.s | 31 + test/MC/ARM/eh-directive-handlerdata.s | 107 + test/MC/ARM/eh-directive-integrated-test.s | 93 + test/MC/ARM/eh-directive-multiple-offsets.s | 168 + test/MC/ARM/eh-directive-pad-diagnostics.s | 39 + test/MC/ARM/eh-directive-pad.s | 226 + test/MC/ARM/eh-directive-personality-diagnostics.s | 39 + test/MC/ARM/eh-directive-personality.s | 89 + test/MC/ARM/eh-directive-save-diagnoatics.s | 41 + test/MC/ARM/eh-directive-save.s | 343 + test/MC/ARM/eh-directive-section-comdat.s | 126 + test/MC/ARM/eh-directive-section-multiple-func.s | 128 + test/MC/ARM/eh-directive-section.s | 163 + test/MC/ARM/eh-directive-setfp-diagnostics.s | 87 + test/MC/ARM/eh-directive-setfp.s | 239 + .../ARM/eh-directive-text-section-multiple-func.s | 81 + test/MC/ARM/eh-directive-text-section.s | 82 + test/MC/ARM/eh-directive-vsave-diagnostics.s | 41 + test/MC/ARM/eh-directive-vsave.s | 130 + test/MC/ARM/elf-eflags-eabi-cg.ll | 14 - test/MC/ARM/elf-movt.s | 24 +- test/MC/ARM/elf-reloc-01.ll | 2 +- test/MC/ARM/elf-reloc-02.ll | 2 +- test/MC/ARM/elf-reloc-03.ll | 2 +- test/MC/ARM/elf-reloc-condcall.s | 2 +- test/MC/ARM/elf-thumbfunc-reloc.ll | 2 +- test/MC/ARM/elf-thumbfunc-reloc.s | 4 +- test/MC/ARM/elf-thumbfunc.s | 2 +- test/MC/ARM/fp-armv8.s | 129 + test/MC/ARM/idiv.s | 33 + test/MC/ARM/invalid-barrier.s | 28 + test/MC/ARM/invalid-crc32.s | 16 + test/MC/ARM/invalid-fp-armv8.s | 89 + test/MC/ARM/invalid-hint-arm.s | 11 +- test/MC/ARM/invalid-hint-thumb.s | 13 +- test/MC/ARM/invalid-idiv.s | 28 + test/MC/ARM/invalid-neon-v8.s | 70 + test/MC/ARM/lit.local.cfg | 2 - test/MC/ARM/load-store-acquire-release-v8-thumb.s | 48 + test/MC/ARM/load-store-acquire-release-v8.s | 48 + test/MC/ARM/mapping-within-section.s | 2 +- test/MC/ARM/multi-section-mapping.s | 2 +- test/MC/ARM/neon-convert-encoding.s | 16 + test/MC/ARM/neon-crypto.s | 51 + test/MC/ARM/neon-mov-encoding.s | 39 + test/MC/ARM/neon-v8.s | 83 + test/MC/ARM/neon-vst-encoding.s | 2 +- test/MC/ARM/neont2-vld-encoding.s | 103 +- test/MC/ARM/neont2-vst-encoding.s | 93 +- test/MC/ARM/obsolete-v8.s | 7 + test/MC/ARM/simple-fp-encoding.s | 22 + test/MC/ARM/single-precision-fp.s | 194 + test/MC/ARM/thumb-diagnostics.s | 72 +- test/MC/ARM/thumb-fp-armv8.s | 130 + test/MC/ARM/thumb-hints.s | 64 + test/MC/ARM/thumb-invalid-crypto.txt | 42 + test/MC/ARM/thumb-neon-crypto.s | 35 + test/MC/ARM/thumb-neon-v8.s | 83 + test/MC/ARM/thumb-nop.s | 9 - test/MC/ARM/thumb-only-conditionals.s | 54 + test/MC/ARM/thumb.s | 2 +- test/MC/ARM/thumb2-b.w-encodingT4.s | 2 +- test/MC/ARM/thumb2-branches.s | 286 + test/MC/ARM/thumb2-diagnostics.s | 28 + test/MC/ARM/thumb2-ldrd.s | 9 + test/MC/ARM/thumb2-pldw.s | 7 + test/MC/ARM/v8_IT_manual.s | 6739 +++++ test/MC/ARM/vfp4.s | 21 +- test/MC/ARM/xscale-attributes.ll | 7 +- test/MC/AsmParser/align_invalid.s | 4 +- test/MC/AsmParser/cfi-window-save.s | 15 + test/MC/AsmParser/directive_align.s | 2 +- test/MC/AsmParser/directive_file.s | 2 +- test/MC/AsmParser/directive_fill.s | 16 + test/MC/AsmParser/directive_incbin.s | 2 +- test/MC/AsmParser/directive_include.s | 2 +- test/MC/AsmParser/directive_loc.s | 1 + test/MC/AsmParser/floating-literals.s | 40 +- test/MC/AsmParser/lit.local.cfg | 2 - test/MC/AsmParser/macros-darwin.s | 2 +- test/MC/AsmParser/secure_log_unique.s | 9 + test/MC/COFF/alias.s | 106 + test/MC/COFF/bss_section.ll | 6 + test/MC/COFF/eh-frame.s | 14 + test/MC/COFF/feat00.s | 14 + test/MC/COFF/linkonce-invalid.s | 40 + test/MC/COFF/linkonce.s | 179 + test/MC/COFF/lit.local.cfg | 2 - test/MC/COFF/lset0.s | 12 + test/MC/COFF/rdata.ll | 6 + test/MC/COFF/section-comdat.s | 188 + test/MC/COFF/section-invalid-flags.s | 8 + test/MC/COFF/section-name-encoding.s | 62 + test/MC/COFF/section.s | 170 + test/MC/COFF/seh-align1.s | 65 + test/MC/COFF/seh-align2.s | 78 + test/MC/COFF/seh-align3.s | 83 + test/MC/COFF/seh-section.s | 2 - test/MC/COFF/seh.s | 25 +- test/MC/COFF/tricky-names.ll | 38 + test/MC/COFF/weak-symbol-section-specification.ll | 25 - test/MC/COFF/weak-symbol.ll | 44 + .../MC/Disassembler/AArch64/a64-ignored-fields.txt | 2 +- .../AArch64/basic-a64-instructions.txt | 2 +- .../AArch64/basic-a64-unpredictable.txt | 2 +- .../AArch64/ldp-postind.predictable.txt | 2 +- .../AArch64/ldp-preind.predictable.txt | 2 +- test/MC/Disassembler/AArch64/lit.local.cfg | 2 - test/MC/Disassembler/AArch64/neon-instructions.txt | 2638 ++ test/MC/Disassembler/ARM/arm-LDREXD-reencoding.txt | 14 + test/MC/Disassembler/ARM/arm-STREXD-reencoding.txt | 14 + test/MC/Disassembler/ARM/arm-tests.txt | 4 - .../Disassembler/ARM/basic-arm-instructions-v8.txt | 58 + .../MC/Disassembler/ARM/basic-arm-instructions.txt | 35 + test/MC/Disassembler/ARM/crc32-thumb.txt | 15 + test/MC/Disassembler/ARM/crc32.txt | 15 + test/MC/Disassembler/ARM/fp-armv8.txt | 160 + test/MC/Disassembler/ARM/fp-encoding.txt | 26 +- test/MC/Disassembler/ARM/invalid-BFI-arm.txt | 10 - test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt | 10 - test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-DMB-thumb.txt | 16 - test/MC/Disassembler/ARM/invalid-DSB-arm.txt | 16 - test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt | 8 + test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt | 5 - test/MC/Disassembler/ARM/invalid-IT-thumb.txt | 3 - test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt | 11 - test/MC/Disassembler/ARM/invalid-LDM-thumb.txt | 5 - test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt | 10 - .../MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt | 13 - test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt | 10 - test/MC/Disassembler/ARM/invalid-LDRrs-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-MCR-arm.txt | 10 - test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt | 10 - test/MC/Disassembler/ARM/invalid-MOVr-arm.txt | 13 - test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt | 9 - test/MC/Disassembler/ARM/invalid-MOVs-arm.txt | 17 - test/MC/Disassembler/ARM/invalid-MRRC2-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-MSRi-arm.txt | 12 - .../MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt | 11 - test/MC/Disassembler/ARM/invalid-SBFX-arm.txt | 10 - test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt | 11 - test/MC/Disassembler/ARM/invalid-SRS-arm.txt | 13 - .../Disassembler/ARM/invalid-STMIA_UPD-thumb.txt | 10 - test/MC/Disassembler/ARM/invalid-SXTB-arm.txt | 11 - test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt | 11 - .../Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt | 11 - .../ARM/invalid-VLD1LNd32_UPD-thumb.txt | 4 - .../ARM/invalid-VLD3DUPd32_UPD-thumb.txt | 11 - .../ARM/invalid-VLD4DUPd32_UPD-thumb.txt | 4 - .../ARM/invalid-VLD4LNd32_UPD-thumb.txt | 4 - .../Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt | 4 - test/MC/Disassembler/ARM/invalid-VQADD-arm.txt | 11 - .../ARM/invalid-VST1LNd32_UPD-thumb.txt | 4 - .../ARM/invalid-VST1d8Twb_register-thumb.txt | 13 - .../Disassembler/ARM/invalid-VST2b32_UPD-arm.txt | 12 - .../ARM/invalid-VST4LNd32_UPD-thumb.txt | 4 - test/MC/Disassembler/ARM/invalid-armv7.txt | 502 + test/MC/Disassembler/ARM/invalid-armv8.txt | 167 + test/MC/Disassembler/ARM/invalid-because-armv7.txt | 26 + test/MC/Disassembler/ARM/invalid-hint-arm.txt | 13 - test/MC/Disassembler/ARM/invalid-hint-thumb.txt | 8 - test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt | 11 - test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt | 10 - .../MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt | 11 - .../Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt | 10 - .../Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt | 10 - test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt | 5 - .../Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt | 11 - .../MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt | 11 - .../MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt | 10 - .../Disassembler/ARM/invalid-t2STR_POST-thumb.txt | 10 - test/MC/Disassembler/ARM/invalid-thumbv7-xfail.txt | 38 + test/MC/Disassembler/ARM/invalid-thumbv7.txt | 407 + test/MC/Disassembler/ARM/invalid-thumbv8.txt | 167 + test/MC/Disassembler/ARM/lit.local.cfg | 2 - .../ARM/load-store-acquire-release-v8-thumb.txt | 33 + .../ARM/load-store-acquire-release-v8.txt | 32 + test/MC/Disassembler/ARM/neon-crypto.txt | 35 + test/MC/Disassembler/ARM/neon-v8.txt | 71 + test/MC/Disassembler/ARM/neont2.txt | 3 - test/MC/Disassembler/ARM/thumb-fp-armv8.txt | 163 + test/MC/Disassembler/ARM/thumb-neon-crypto.txt | 43 + test/MC/Disassembler/ARM/thumb-neon-v8.txt | 71 + test/MC/Disassembler/ARM/thumb-tests.txt | 5 +- test/MC/Disassembler/ARM/thumb-v8.txt | 28 + test/MC/Disassembler/ARM/thumb1.txt | 16 +- test/MC/Disassembler/ARM/thumb2-v8.txt | 40 + test/MC/Disassembler/ARM/thumb2.txt | 116 +- test/MC/Disassembler/MBlaze/lit.local.cfg | 6 - test/MC/Disassembler/MBlaze/mblaze_branch.txt | 119 - test/MC/Disassembler/MBlaze/mblaze_fpu.txt | 47 - test/MC/Disassembler/MBlaze/mblaze_fsl.txt | 338 - test/MC/Disassembler/MBlaze/mblaze_imm.txt | 121 - test/MC/Disassembler/MBlaze/mblaze_mbar.txt | 14 - test/MC/Disassembler/MBlaze/mblaze_memory.txt | 65 - test/MC/Disassembler/MBlaze/mblaze_operands.txt | 197 - test/MC/Disassembler/MBlaze/mblaze_pattern.txt | 17 - test/MC/Disassembler/MBlaze/mblaze_shift.txt | 29 - test/MC/Disassembler/MBlaze/mblaze_special.txt | 105 - test/MC/Disassembler/MBlaze/mblaze_typea.txt | 74 - test/MC/Disassembler/MBlaze/mblaze_typeb.txt | 56 - test/MC/Disassembler/Mips/lit.local.cfg | 2 - test/MC/Disassembler/Mips/micromips.txt | 287 + test/MC/Disassembler/Mips/micromips_le.txt | 287 + test/MC/Disassembler/Mips/mips-dsp.txt | 9 + test/MC/Disassembler/Mips/mips32.txt | 24 + test/MC/Disassembler/Mips/mips32_le.txt | 30 + test/MC/Disassembler/Mips/mips32r2.txt | 18 + test/MC/Disassembler/Mips/mips32r2_le.txt | 18 + test/MC/Disassembler/Mips/mips64.txt | 21 + test/MC/Disassembler/Mips/mips64_le.txt | 18 + test/MC/Disassembler/SystemZ/insns-pcrel.txt | 1732 ++ test/MC/Disassembler/SystemZ/insns.txt | 7751 ++++++ test/MC/Disassembler/SystemZ/invalid-regs.txt | 22 + test/MC/Disassembler/SystemZ/lit.local.cfg | 4 + test/MC/Disassembler/SystemZ/trunc-01.txt | 5 + test/MC/Disassembler/SystemZ/trunc-02.txt | 5 + test/MC/Disassembler/SystemZ/trunc-03.txt | 5 + test/MC/Disassembler/SystemZ/unmapped.txt | 32 + test/MC/Disassembler/X86/intel-syntax-32.txt | 26 +- test/MC/Disassembler/X86/intel-syntax.txt | 85 +- test/MC/Disassembler/X86/lit.local.cfg | 2 - test/MC/Disassembler/X86/prefixes.txt | 59 + test/MC/Disassembler/X86/simple-tests.txt | 152 +- test/MC/Disassembler/X86/x86-32.txt | 48 + test/MC/Disassembler/X86/x86-64.txt | 114 + test/MC/Disassembler/XCore/lit.local.cfg | 2 - test/MC/ELF/alias-reloc.s | 13 +- test/MC/ELF/alias.s | 9 + test/MC/ELF/bad-relocation.s | 7 + test/MC/ELF/basic-elf-32.s | 2 +- test/MC/ELF/basic-elf-64.s | 2 +- test/MC/ELF/bss-large.ll | 13 + test/MC/ELF/cfi-adjust-cfa-offset.s | 2 +- test/MC/ELF/cfi-advance-loc2.s | 2 +- test/MC/ELF/cfi-def-cfa-offset.s | 2 +- test/MC/ELF/cfi-def-cfa-register.s | 2 +- test/MC/ELF/cfi-def-cfa.s | 2 +- test/MC/ELF/cfi-escape.s | 2 +- test/MC/ELF/cfi-offset.s | 2 +- test/MC/ELF/cfi-register.s | 2 +- test/MC/ELF/cfi-rel-offset.s | 2 +- test/MC/ELF/cfi-rel-offset2.s | 2 +- test/MC/ELF/cfi-remember.s | 2 +- test/MC/ELF/cfi-restore.s | 2 +- test/MC/ELF/cfi-same-value.s | 2 +- test/MC/ELF/cfi-undefined.s | 2 +- test/MC/ELF/cfi-window-save.s | 51 + test/MC/ELF/cfi-zero-addr-delta.s | 2 +- test/MC/ELF/cfi.s | 144 +- test/MC/ELF/comdat-dup-group-name.s | 41 + test/MC/ELF/comdat-reloc.s | 29 + test/MC/ELF/comdat.s | 4 +- test/MC/ELF/comp-dir.s | 10 + test/MC/ELF/debug-line.s | 29 +- test/MC/ELF/debug-line2.s | 32 + test/MC/ELF/file-double.s | 47 + test/MC/ELF/gen-dwarf.s | 4 +- test/MC/ELF/got.s | 2 +- test/MC/ELF/lit.local.cfg | 2 - test/MC/ELF/local-reloc.s | 2 +- test/MC/ELF/merge.s | 2 +- test/MC/ELF/relocation-386.s | 2 +- test/MC/ELF/relocation-pc.s | 4 +- test/MC/ELF/relocation.s | 19 +- test/MC/ELF/rename.s | 17 + test/MC/ELF/section.s | 27 +- test/MC/ELF/symbol-names.s | 12 + test/MC/ELF/symref.s | 2 +- test/MC/ELF/type.s | 28 + test/MC/ELF/weak-relocation.s | 2 +- test/MC/ELF/weakref.s | 9 + test/MC/ELF/x86_64-reloc-sizetest.s | 2 +- test/MC/MBlaze/lit.local.cfg | 6 - test/MC/MBlaze/mblaze_branch.s | 197 - test/MC/MBlaze/mblaze_fpu.s | 77 - test/MC/MBlaze/mblaze_fsl.s | 568 - test/MC/MBlaze/mblaze_imm.s | 194 - test/MC/MBlaze/mblaze_memory.s | 107 - test/MC/MBlaze/mblaze_operands.s | 328 - test/MC/MBlaze/mblaze_pattern.s | 22 - test/MC/MBlaze/mblaze_shift.s | 47 - test/MC/MBlaze/mblaze_special.s | 167 - test/MC/MBlaze/mblaze_typea.s | 122 - test/MC/MBlaze/mblaze_typeb.s | 92 - test/MC/MachO/ARM/lit.local.cfg | 2 - test/MC/MachO/bad-darwin-x86_64-32-bit-abs-addr.s | 5 + test/MC/MachO/bad-darwin-x86_64-diff-relocs.s | 5 + test/MC/MachO/bad-indirect-symbols.s | 5 + test/MC/MachO/bss.s | 17 + test/MC/MachO/darwin-x86_64-diff-reloc-assign-2.s | 38 + test/MC/MachO/lit.local.cfg | 2 - test/MC/MachO/tlv-bss.ll | 33 + test/MC/Mips/abicalls.ll | 15 + test/MC/Mips/eh-frame.s | 8 +- test/MC/Mips/elf-gprel-32-64.ll | 2 +- test/MC/Mips/elf-tls.ll | 2 +- test/MC/Mips/elf_eflags.ll | 51 +- test/MC/Mips/elf_eflags.s | 5 + test/MC/Mips/elf_st_other.ll | 5 +- test/MC/Mips/elf_st_other.s | 13 + test/MC/Mips/lit.local.cfg | 2 - test/MC/Mips/micromips-alu-instructions.s | 104 +- test/MC/Mips/micromips-branch-instructions.s | 65 + test/MC/Mips/micromips-branch16.s | 69 + test/MC/Mips/micromips-expansions.s | 57 + test/MC/Mips/micromips-expressions.s | 35 + test/MC/Mips/micromips-jump-instructions.s | 40 + test/MC/Mips/micromips-jump26.s | 23 + test/MC/Mips/micromips-loadstore-instructions.s | 32 +- test/MC/Mips/micromips-loadstore-unaligned.s | 26 + test/MC/Mips/micromips-long-branch.ll | 16437 ++++++++++++ test/MC/Mips/micromips-movcond-instructions.s | 26 + test/MC/Mips/micromips-multiply-instructions.s | 26 + test/MC/Mips/micromips-relocations.s | 99 + test/MC/Mips/micromips-shift-instructions.s | 32 +- test/MC/Mips/micromips-tailr.s | 26 + test/MC/Mips/micromips-trap-instructions.s | 50 + test/MC/Mips/mips-alu-instructions.s | 16 +- test/MC/Mips/mips-control-instructions.s | 106 + test/MC/Mips/mips-dsp-instructions.s | 97 + test/MC/Mips/mips-fpu-instructions.s | 35 +- test/MC/Mips/mips-jump-instructions.s | 16 +- test/MC/Mips/mips64-alu-instructions.s | 10 +- test/MC/Mips/mips64-instructions.s | 7 + test/MC/Mips/mips_directives.s | 14 +- test/MC/Mips/msa/test_2r.s | 51 + test/MC/Mips/msa/test_2rf.s | 102 + test/MC/Mips/msa/test_3r.s | 732 + test/MC/Mips/msa/test_3rf.s | 252 + test/MC/Mips/msa/test_bit.s | 150 + test/MC/Mips/msa/test_cbranch.s | 78 + test/MC/Mips/msa/test_ctrlregs.s | 105 + test/MC/Mips/msa/test_elm.s | 51 + test/MC/Mips/msa/test_elm_insert.s | 15 + test/MC/Mips/msa/test_elm_insve.s | 18 + test/MC/Mips/msa/test_i10.s | 19 + test/MC/Mips/msa/test_i5.s | 138 + test/MC/Mips/msa/test_i8.s | 36 + test/MC/Mips/msa/test_lsa.s | 18 + test/MC/Mips/msa/test_mi10.s | 30 + test/MC/Mips/msa/test_vec.s | 27 + test/MC/Mips/xgot.ll | 4 +- test/MC/PowerPC/deprecated-p7.s | 12 + test/MC/PowerPC/lit.local.cfg | 2 - test/MC/PowerPC/ppc-llong.s | 28 + test/MC/PowerPC/ppc-machine.s | 14 + test/MC/PowerPC/ppc-nop.s | 12 + test/MC/PowerPC/ppc-word.s | 28 + test/MC/PowerPC/ppc64-encoding-bookII.s | 48 +- test/MC/PowerPC/ppc64-encoding-bookIII.s | 107 + test/MC/PowerPC/ppc64-encoding-ext.s | 2154 +- test/MC/PowerPC/ppc64-encoding-fp.s | 18 +- test/MC/PowerPC/ppc64-encoding.s | 137 +- test/MC/PowerPC/ppc64-errors.s | 21 + test/MC/PowerPC/ppc64-fixup-apply.s | 100 + test/MC/PowerPC/ppc64-fixup-explicit.s | 46 + test/MC/PowerPC/ppc64-fixups.s | 399 +- test/MC/PowerPC/ppc64-initial-cfa.ll | 84 - test/MC/PowerPC/ppc64-initial-cfa.s | 84 + test/MC/PowerPC/ppc64-operands.s | 28 + test/MC/PowerPC/ppc64-regs.s | 235 + test/MC/PowerPC/ppc64-relocs-01.ll | 49 - test/MC/PowerPC/ppc64-relocs-01.s | 46 + test/MC/PowerPC/ppc64-tls-relocs-01.ll | 19 - test/MC/PowerPC/ppc64-tls-relocs-01.s | 22 + test/MC/PowerPC/tls-gd-obj.s | 56 + test/MC/PowerPC/tls-ie-obj.s | 44 + test/MC/PowerPC/tls-ld-obj.s | 61 + test/MC/SystemZ/insn-a-01.s | 17 - test/MC/SystemZ/insn-a-02.s | 10 - test/MC/SystemZ/insn-adb-01.s | 17 - test/MC/SystemZ/insn-adb-02.s | 10 - test/MC/SystemZ/insn-adbr-01.s | 11 - test/MC/SystemZ/insn-aeb-01.s | 17 - test/MC/SystemZ/insn-aeb-02.s | 10 - test/MC/SystemZ/insn-aebr-01.s | 11 - test/MC/SystemZ/insn-afi-01.s | 15 - test/MC/SystemZ/insn-afi-02.s | 10 - test/MC/SystemZ/insn-ag-01.s | 23 - test/MC/SystemZ/insn-ag-02.s | 10 - test/MC/SystemZ/insn-agf-01.s | 23 - test/MC/SystemZ/insn-agf-02.s | 10 - test/MC/SystemZ/insn-agfi-01.s | 15 - test/MC/SystemZ/insn-agfi-02.s | 10 - test/MC/SystemZ/insn-agfr-01.s | 11 - test/MC/SystemZ/insn-aghi-01.s | 15 - test/MC/SystemZ/insn-aghi-02.s | 13 - test/MC/SystemZ/insn-agr-01.s | 11 - test/MC/SystemZ/insn-agsi-01.s | 29 - test/MC/SystemZ/insn-agsi-02.s | 19 - test/MC/SystemZ/insn-ah-01.s | 17 - test/MC/SystemZ/insn-ah-02.s | 10 - test/MC/SystemZ/insn-ahi-01.s | 15 - test/MC/SystemZ/insn-ahi-02.s | 13 - test/MC/SystemZ/insn-ahy-01.s | 23 - test/MC/SystemZ/insn-ahy-02.s | 10 - test/MC/SystemZ/insn-al-01.s | 17 - test/MC/SystemZ/insn-al-02.s | 10 - test/MC/SystemZ/insn-alc-01.s | 23 - test/MC/SystemZ/insn-alc-02.s | 10 - test/MC/SystemZ/insn-alcg-01.s | 23 - test/MC/SystemZ/insn-alcg-02.s | 10 - test/MC/SystemZ/insn-alcgr-01.s | 11 - test/MC/SystemZ/insn-alcr-01.s | 11 - test/MC/SystemZ/insn-alfi-01.s | 9 - test/MC/SystemZ/insn-alfi-02.s | 10 - test/MC/SystemZ/insn-alg-01.s | 23 - test/MC/SystemZ/insn-alg-02.s | 10 - test/MC/SystemZ/insn-algf-01.s | 23 - test/MC/SystemZ/insn-algf-02.s | 10 - test/MC/SystemZ/insn-algfi-01.s | 9 - test/MC/SystemZ/insn-algfi-02.s | 10 - test/MC/SystemZ/insn-algfr-01.s | 11 - test/MC/SystemZ/insn-algr-01.s | 11 - test/MC/SystemZ/insn-alr-01.s | 11 - test/MC/SystemZ/insn-aly-01.s | 23 - test/MC/SystemZ/insn-aly-02.s | 10 - test/MC/SystemZ/insn-ar-01.s | 11 - test/MC/SystemZ/insn-asi-01.s | 29 - test/MC/SystemZ/insn-asi-02.s | 19 - test/MC/SystemZ/insn-axbr-01.s | 11 - test/MC/SystemZ/insn-axbr-02.s | 17 - test/MC/SystemZ/insn-ay-01.s | 23 - test/MC/SystemZ/insn-ay-02.s | 10 - test/MC/SystemZ/insn-bad-z196.s | 343 + test/MC/SystemZ/insn-bad.s | 3315 +++ test/MC/SystemZ/insn-basr-01.s | 12 - test/MC/SystemZ/insn-br-01.s | 9 - test/MC/SystemZ/insn-bras-01.s | 31 - test/MC/SystemZ/insn-brasl-01.s | 31 - test/MC/SystemZ/insn-brc-01.s | 238 - test/MC/SystemZ/insn-brc-02.s | 13 - test/MC/SystemZ/insn-brcl-01.s | 238 - test/MC/SystemZ/insn-brcl-02.s | 13 - test/MC/SystemZ/insn-c-01.s | 17 - test/MC/SystemZ/insn-c-02.s | 10 - test/MC/SystemZ/insn-cdb-01.s | 17 - test/MC/SystemZ/insn-cdb-02.s | 10 - test/MC/SystemZ/insn-cdbr-01.s | 11 - test/MC/SystemZ/insn-cdfbr-01.s | 13 - test/MC/SystemZ/insn-cdfbr-02.s | 16 - test/MC/SystemZ/insn-cdgbr-01.s | 13 - test/MC/SystemZ/insn-cdgbr-02.s | 16 - test/MC/SystemZ/insn-ceb-01.s | 17 - test/MC/SystemZ/insn-ceb-02.s | 10 - test/MC/SystemZ/insn-cebr-01.s | 11 - test/MC/SystemZ/insn-cefbr-01.s | 13 - test/MC/SystemZ/insn-cefbr-02.s | 16 - test/MC/SystemZ/insn-cegbr-01.s | 13 - test/MC/SystemZ/insn-cegbr-02.s | 16 - test/MC/SystemZ/insn-cfdbr-01.s | 13 - test/MC/SystemZ/insn-cfdbr-02.s | 16 - test/MC/SystemZ/insn-cfebr-01.s | 13 - test/MC/SystemZ/insn-cfebr-02.s | 16 - test/MC/SystemZ/insn-cfi-01.s | 15 - test/MC/SystemZ/insn-cfi-02.s | 10 - test/MC/SystemZ/insn-cfxbr-01.s | 13 - test/MC/SystemZ/insn-cfxbr-02.s | 23 - test/MC/SystemZ/insn-cg-01.s | 23 - test/MC/SystemZ/insn-cg-02.s | 10 - test/MC/SystemZ/insn-cgdbr-01.s | 13 - test/MC/SystemZ/insn-cgdbr-02.s | 16 - test/MC/SystemZ/insn-cgebr-01.s | 13 - test/MC/SystemZ/insn-cgebr-02.s | 16 - test/MC/SystemZ/insn-cgf-01.s | 23 - test/MC/SystemZ/insn-cgf-02.s | 10 - test/MC/SystemZ/insn-cgfi-01.s | 15 - test/MC/SystemZ/insn-cgfi-02.s | 10 - test/MC/SystemZ/insn-cgfr-01.s | 11 - test/MC/SystemZ/insn-cgfrl-01.s | 31 - test/MC/SystemZ/insn-cgh-01.s | 23 - test/MC/SystemZ/insn-cgh-02.s | 10 - test/MC/SystemZ/insn-cghi-01.s | 15 - test/MC/SystemZ/insn-cghi-02.s | 13 - test/MC/SystemZ/insn-cghrl-01.s | 31 - test/MC/SystemZ/insn-cghsi-01.s | 25 - test/MC/SystemZ/insn-cghsi-02.s | 19 - test/MC/SystemZ/insn-cgr-01.s | 11 - test/MC/SystemZ/insn-cgrl-01.s | 31 - test/MC/SystemZ/insn-cgxbr-01.s | 13 - test/MC/SystemZ/insn-cgxbr-02.s | 23 - test/MC/SystemZ/insn-ch-01.s | 17 - test/MC/SystemZ/insn-ch-02.s | 10 - test/MC/SystemZ/insn-chhsi-01.s | 25 - test/MC/SystemZ/insn-chhsi-02.s | 19 - test/MC/SystemZ/insn-chi-01.s | 15 - test/MC/SystemZ/insn-chi-02.s | 13 - test/MC/SystemZ/insn-chrl-01.s | 31 - test/MC/SystemZ/insn-chsi-01.s | 25 - test/MC/SystemZ/insn-chsi-02.s | 19 - test/MC/SystemZ/insn-chy-01.s | 23 - test/MC/SystemZ/insn-chy-02.s | 10 - test/MC/SystemZ/insn-cl-01.s | 17 - test/MC/SystemZ/insn-cl-02.s | 10 - test/MC/SystemZ/insn-clfhsi-01.s | 17 - test/MC/SystemZ/insn-clfhsi-02.s | 19 - test/MC/SystemZ/insn-clfi-01.s | 9 - test/MC/SystemZ/insn-clfi-02.s | 10 - test/MC/SystemZ/insn-clg-01.s | 23 - test/MC/SystemZ/insn-clg-02.s | 10 - test/MC/SystemZ/insn-clgf-01.s | 23 - test/MC/SystemZ/insn-clgf-02.s | 10 - test/MC/SystemZ/insn-clgfi-01.s | 9 - test/MC/SystemZ/insn-clgfi-02.s | 10 - test/MC/SystemZ/insn-clgfr-01.s | 11 - test/MC/SystemZ/insn-clgfrl-01.s | 31 - test/MC/SystemZ/insn-clghrl-01.s | 31 - test/MC/SystemZ/insn-clghsi-01.s | 17 - test/MC/SystemZ/insn-clghsi-02.s | 19 - test/MC/SystemZ/insn-clgr-01.s | 11 - test/MC/SystemZ/insn-clgrl-01.s | 31 - test/MC/SystemZ/insn-clhhsi-01.s | 17 - test/MC/SystemZ/insn-clhhsi-02.s | 19 - test/MC/SystemZ/insn-clhrl-01.s | 31 - test/MC/SystemZ/insn-cli-01.s | 17 - test/MC/SystemZ/insn-cli-02.s | 19 - test/MC/SystemZ/insn-cliy-01.s | 23 - test/MC/SystemZ/insn-cliy-02.s | 19 - test/MC/SystemZ/insn-clr-01.s | 11 - test/MC/SystemZ/insn-clrl-01.s | 31 - test/MC/SystemZ/insn-cly-01.s | 23 - test/MC/SystemZ/insn-cly-02.s | 10 - test/MC/SystemZ/insn-cpsdr-01.s | 16 - test/MC/SystemZ/insn-cr-01.s | 11 - test/MC/SystemZ/insn-crl-01.s | 31 - test/MC/SystemZ/insn-cs-01.s | 19 - test/MC/SystemZ/insn-cs-02.s | 13 - test/MC/SystemZ/insn-csg-01.s | 25 - test/MC/SystemZ/insn-csg-02.s | 13 - test/MC/SystemZ/insn-csy-01.s | 25 - test/MC/SystemZ/insn-csy-02.s | 13 - test/MC/SystemZ/insn-cxbr-01.s | 11 - test/MC/SystemZ/insn-cxbr-02.s | 17 - test/MC/SystemZ/insn-cxfbr-01.s | 13 - test/MC/SystemZ/insn-cxfbr-02.s | 22 - test/MC/SystemZ/insn-cxgbr-01.s | 13 - test/MC/SystemZ/insn-cxgbr-02.s | 22 - test/MC/SystemZ/insn-cy-01.s | 23 - test/MC/SystemZ/insn-cy-02.s | 10 - test/MC/SystemZ/insn-ddb-01.s | 17 - test/MC/SystemZ/insn-ddb-02.s | 10 - test/MC/SystemZ/insn-ddbr-01.s | 11 - test/MC/SystemZ/insn-deb-01.s | 17 - test/MC/SystemZ/insn-deb-02.s | 10 - test/MC/SystemZ/insn-debr-01.s | 11 - test/MC/SystemZ/insn-dl-01.s | 23 - test/MC/SystemZ/insn-dl-02.s | 16 - test/MC/SystemZ/insn-dlg-01.s | 23 - test/MC/SystemZ/insn-dlg-02.s | 16 - test/MC/SystemZ/insn-dlgr-01.s | 11 - test/MC/SystemZ/insn-dlgr-02.s | 10 - test/MC/SystemZ/insn-dlr-01.s | 11 - test/MC/SystemZ/insn-dlr-02.s | 10 - test/MC/SystemZ/insn-dsg-01.s | 23 - test/MC/SystemZ/insn-dsg-02.s | 16 - test/MC/SystemZ/insn-dsgf-01.s | 23 - test/MC/SystemZ/insn-dsgf-02.s | 16 - test/MC/SystemZ/insn-dsgfr-01.s | 11 - test/MC/SystemZ/insn-dsgfr-02.s | 10 - test/MC/SystemZ/insn-dsgr-01.s | 11 - test/MC/SystemZ/insn-dsgr-02.s | 10 - test/MC/SystemZ/insn-dxbr-01.s | 11 - test/MC/SystemZ/insn-dxbr-02.s | 17 - test/MC/SystemZ/insn-ear-01.s | 13 - test/MC/SystemZ/insn-ear-02.s | 13 - test/MC/SystemZ/insn-fidbr-01.s | 13 - test/MC/SystemZ/insn-fidbr-02.s | 16 - test/MC/SystemZ/insn-fiebr-01.s | 13 - test/MC/SystemZ/insn-fiebr-02.s | 16 - test/MC/SystemZ/insn-fixbr-01.s | 13 - test/MC/SystemZ/insn-fixbr-02.s | 28 - test/MC/SystemZ/insn-flogr-01.s | 11 - test/MC/SystemZ/insn-flogr-02.s | 10 - test/MC/SystemZ/insn-good-z196.s | 916 + test/MC/SystemZ/insn-good.s | 8580 +++++++ test/MC/SystemZ/insn-ic-01.s | 17 - test/MC/SystemZ/insn-ic-02.s | 10 - test/MC/SystemZ/insn-icy-01.s | 23 - test/MC/SystemZ/insn-icy-02.s | 10 - test/MC/SystemZ/insn-iihf-01.s | 9 - test/MC/SystemZ/insn-iihf-02.s | 10 - test/MC/SystemZ/insn-iihh-01.s | 11 - test/MC/SystemZ/insn-iihh-02.s | 10 - test/MC/SystemZ/insn-iihl-01.s | 11 - test/MC/SystemZ/insn-iihl-02.s | 10 - test/MC/SystemZ/insn-iilf-01.s | 9 - test/MC/SystemZ/insn-iilf-02.s | 10 - test/MC/SystemZ/insn-iilh-01.s | 11 - test/MC/SystemZ/insn-iilh-02.s | 10 - test/MC/SystemZ/insn-iill-01.s | 11 - test/MC/SystemZ/insn-iill-02.s | 10 - test/MC/SystemZ/insn-l-01.s | 17 - test/MC/SystemZ/insn-l-02.s | 10 - test/MC/SystemZ/insn-la-01.s | 17 - test/MC/SystemZ/insn-la-02.s | 10 - test/MC/SystemZ/insn-larl-01.s | 31 - test/MC/SystemZ/insn-lay-01.s | 23 - test/MC/SystemZ/insn-lay-02.s | 10 - test/MC/SystemZ/insn-lb-01.s | 23 - test/MC/SystemZ/insn-lb-02.s | 10 - test/MC/SystemZ/insn-lbr-01.s | 9 - test/MC/SystemZ/insn-lcdbr-01.s | 11 - test/MC/SystemZ/insn-lcebr-01.s | 11 - test/MC/SystemZ/insn-lcgfr-01.s | 11 - test/MC/SystemZ/insn-lcgr-01.s | 11 - test/MC/SystemZ/insn-lcr-01.s | 11 - test/MC/SystemZ/insn-lcxbr-01.s | 11 - test/MC/SystemZ/insn-lcxbr-02.s | 17 - test/MC/SystemZ/insn-ld-01.s | 17 - test/MC/SystemZ/insn-ld-02.s | 10 - test/MC/SystemZ/insn-ldeb-01.s | 17 - test/MC/SystemZ/insn-ldeb-02.s | 10 - test/MC/SystemZ/insn-ldebr-01.s | 9 - test/MC/SystemZ/insn-ldgr-01.s | 13 - test/MC/SystemZ/insn-ldgr-02.s | 16 - test/MC/SystemZ/insn-ldr-01.s | 11 - test/MC/SystemZ/insn-ldxbr-01.s | 13 - test/MC/SystemZ/insn-ldxbr-02.s | 16 - test/MC/SystemZ/insn-ldy-01.s | 23 - test/MC/SystemZ/insn-ldy-02.s | 10 - test/MC/SystemZ/insn-le-01.s | 17 - test/MC/SystemZ/insn-le-02.s | 10 - test/MC/SystemZ/insn-ledbr-01.s | 13 - test/MC/SystemZ/insn-ler-01.s | 11 - test/MC/SystemZ/insn-lexbr-01.s | 13 - test/MC/SystemZ/insn-lexbr-02.s | 16 - test/MC/SystemZ/insn-ley-01.s | 23 - test/MC/SystemZ/insn-ley-02.s | 10 - test/MC/SystemZ/insn-lg-01.s | 23 - test/MC/SystemZ/insn-lg-02.s | 10 - test/MC/SystemZ/insn-lgb-01.s | 24 - test/MC/SystemZ/insn-lgb-02.s | 10 - test/MC/SystemZ/insn-lgbr-01.s | 9 - test/MC/SystemZ/insn-lgdr-01.s | 13 - test/MC/SystemZ/insn-lgdr-02.s | 16 - test/MC/SystemZ/insn-lgf-01.s | 24 - test/MC/SystemZ/insn-lgf-02.s | 10 - test/MC/SystemZ/insn-lgfi-01.s | 15 - test/MC/SystemZ/insn-lgfi-02.s | 10 - test/MC/SystemZ/insn-lgfr-01.s | 9 - test/MC/SystemZ/insn-lgfrl-01.s | 31 - test/MC/SystemZ/insn-lgh-01.s | 24 - test/MC/SystemZ/insn-lgh-02.s | 10 - test/MC/SystemZ/insn-lghi-01.s | 15 - test/MC/SystemZ/insn-lghi-02.s | 13 - test/MC/SystemZ/insn-lghr-01.s | 9 - test/MC/SystemZ/insn-lghrl-01.s | 31 - test/MC/SystemZ/insn-lgr-01.s | 11 - test/MC/SystemZ/insn-lgrl-01.s | 31 - test/MC/SystemZ/insn-lh-01.s | 17 - test/MC/SystemZ/insn-lh-02.s | 10 - test/MC/SystemZ/insn-lhi-01.s | 15 - test/MC/SystemZ/insn-lhi-02.s | 13 - test/MC/SystemZ/insn-lhr-01.s | 9 - test/MC/SystemZ/insn-lhrl-01.s | 31 - test/MC/SystemZ/insn-lhy-01.s | 23 - test/MC/SystemZ/insn-lhy-02.s | 10 - test/MC/SystemZ/insn-llc-01.s | 23 - test/MC/SystemZ/insn-llc-02.s | 10 - test/MC/SystemZ/insn-llcr-01.s | 9 - test/MC/SystemZ/insn-llgc-01.s | 24 - test/MC/SystemZ/insn-llgc-02.s | 10 - test/MC/SystemZ/insn-llgcr-01.s | 9 - test/MC/SystemZ/insn-llgf-01.s | 24 - test/MC/SystemZ/insn-llgf-02.s | 10 - test/MC/SystemZ/insn-llgfr-01.s | 9 - test/MC/SystemZ/insn-llgfrl-01.s | 31 - test/MC/SystemZ/insn-llgh-01.s | 24 - test/MC/SystemZ/insn-llgh-02.s | 10 - test/MC/SystemZ/insn-llghr-01.s | 9 - test/MC/SystemZ/insn-llghrl-01.s | 31 - test/MC/SystemZ/insn-llh-01.s | 23 - test/MC/SystemZ/insn-llh-02.s | 10 - test/MC/SystemZ/insn-llhr-01.s | 9 - test/MC/SystemZ/insn-llhrl-01.s | 31 - test/MC/SystemZ/insn-llihf-01.s | 9 - test/MC/SystemZ/insn-llihf-02.s | 10 - test/MC/SystemZ/insn-llihh-01.s | 11 - test/MC/SystemZ/insn-llihh-02.s | 10 - test/MC/SystemZ/insn-llihl-01.s | 11 - test/MC/SystemZ/insn-llihl-02.s | 10 - test/MC/SystemZ/insn-llilf-01.s | 9 - test/MC/SystemZ/insn-llilf-02.s | 10 - test/MC/SystemZ/insn-llilh-01.s | 11 - test/MC/SystemZ/insn-llilh-02.s | 10 - test/MC/SystemZ/insn-llill-01.s | 11 - test/MC/SystemZ/insn-llill-02.s | 10 - test/MC/SystemZ/insn-lmg-01.s | 29 - test/MC/SystemZ/insn-lmg-02.s | 13 - test/MC/SystemZ/insn-lndbr-01.s | 11 - test/MC/SystemZ/insn-lnebr-01.s | 11 - test/MC/SystemZ/insn-lnxbr-01.s | 11 - test/MC/SystemZ/insn-lnxbr-02.s | 17 - test/MC/SystemZ/insn-lpdbr-01.s | 11 - test/MC/SystemZ/insn-lpebr-01.s | 11 - test/MC/SystemZ/insn-lpxbr-01.s | 11 - test/MC/SystemZ/insn-lpxbr-02.s | 17 - test/MC/SystemZ/insn-lr-01.s | 11 - test/MC/SystemZ/insn-lrl-01.s | 31 - test/MC/SystemZ/insn-lrv-01.s | 23 - test/MC/SystemZ/insn-lrv-02.s | 10 - test/MC/SystemZ/insn-lrvg-01.s | 23 - test/MC/SystemZ/insn-lrvg-02.s | 10 - test/MC/SystemZ/insn-lrvgr-01.s | 13 - test/MC/SystemZ/insn-lrvr-01.s | 13 - test/MC/SystemZ/insn-lxr-01.s | 11 - test/MC/SystemZ/insn-lxr-02.s | 16 - test/MC/SystemZ/insn-ly-01.s | 23 - test/MC/SystemZ/insn-ly-02.s | 10 - test/MC/SystemZ/insn-lzdr-01.s | 9 - test/MC/SystemZ/insn-lzer-01.s | 9 - test/MC/SystemZ/insn-lzxr-01.s | 9 - test/MC/SystemZ/insn-lzxr-02.s | 13 - test/MC/SystemZ/insn-madb-01.s | 21 - test/MC/SystemZ/insn-madb-02.s | 10 - test/MC/SystemZ/insn-madbr-01.s | 15 - test/MC/SystemZ/insn-maeb-01.s | 21 - test/MC/SystemZ/insn-maeb-02.s | 10 - test/MC/SystemZ/insn-maebr-01.s | 15 - test/MC/SystemZ/insn-mdb-01.s | 17 - test/MC/SystemZ/insn-mdb-02.s | 10 - test/MC/SystemZ/insn-mdbr-01.s | 11 - test/MC/SystemZ/insn-mdeb-01.s | 17 - test/MC/SystemZ/insn-mdeb-02.s | 10 - test/MC/SystemZ/insn-mdebr-01.s | 11 - test/MC/SystemZ/insn-meeb-01.s | 17 - test/MC/SystemZ/insn-meeb-02.s | 10 - test/MC/SystemZ/insn-meebr-01.s | 11 - test/MC/SystemZ/insn-mghi-01.s | 15 - test/MC/SystemZ/insn-mghi-02.s | 13 - test/MC/SystemZ/insn-mh-01.s | 17 - test/MC/SystemZ/insn-mh-02.s | 10 - test/MC/SystemZ/insn-mhi-01.s | 15 - test/MC/SystemZ/insn-mhi-02.s | 13 - test/MC/SystemZ/insn-mhy-01.s | 23 - test/MC/SystemZ/insn-mhy-02.s | 10 - test/MC/SystemZ/insn-mlg-01.s | 23 - test/MC/SystemZ/insn-mlg-02.s | 16 - test/MC/SystemZ/insn-mlgr-01.s | 11 - test/MC/SystemZ/insn-mlgr-02.s | 10 - test/MC/SystemZ/insn-ms-01.s | 17 - test/MC/SystemZ/insn-ms-02.s | 10 - test/MC/SystemZ/insn-msdb-01.s | 21 - test/MC/SystemZ/insn-msdb-02.s | 10 - test/MC/SystemZ/insn-msdbr-01.s | 15 - test/MC/SystemZ/insn-mseb-01.s | 21 - test/MC/SystemZ/insn-mseb-02.s | 10 - test/MC/SystemZ/insn-msebr-01.s | 15 - test/MC/SystemZ/insn-msfi-01.s | 15 - test/MC/SystemZ/insn-msfi-02.s | 10 - test/MC/SystemZ/insn-msg-01.s | 23 - test/MC/SystemZ/insn-msg-02.s | 10 - test/MC/SystemZ/insn-msgf-01.s | 23 - test/MC/SystemZ/insn-msgf-02.s | 10 - test/MC/SystemZ/insn-msgfi-01.s | 15 - test/MC/SystemZ/insn-msgfi-02.s | 10 - test/MC/SystemZ/insn-msgfr-01.s | 11 - test/MC/SystemZ/insn-msgr-01.s | 11 - test/MC/SystemZ/insn-msr-01.s | 11 - test/MC/SystemZ/insn-msy-01.s | 23 - test/MC/SystemZ/insn-msy-02.s | 10 - test/MC/SystemZ/insn-mvghi-01.s | 25 - test/MC/SystemZ/insn-mvghi-02.s | 19 - test/MC/SystemZ/insn-mvhhi-01.s | 25 - test/MC/SystemZ/insn-mvhhi-02.s | 19 - test/MC/SystemZ/insn-mvhi-01.s | 25 - test/MC/SystemZ/insn-mvhi-02.s | 19 - test/MC/SystemZ/insn-mvi-01.s | 17 - test/MC/SystemZ/insn-mvi-02.s | 19 - test/MC/SystemZ/insn-mviy-01.s | 23 - test/MC/SystemZ/insn-mviy-02.s | 19 - test/MC/SystemZ/insn-mxbr-01.s | 11 - test/MC/SystemZ/insn-mxbr-02.s | 17 - test/MC/SystemZ/insn-mxdb-01.s | 17 - test/MC/SystemZ/insn-mxdb-02.s | 16 - test/MC/SystemZ/insn-mxdbr-01.s | 11 - test/MC/SystemZ/insn-mxdbr-02.s | 10 - test/MC/SystemZ/insn-n-01.s | 17 - test/MC/SystemZ/insn-n-02.s | 10 - test/MC/SystemZ/insn-ng-01.s | 23 - test/MC/SystemZ/insn-ng-02.s | 10 - test/MC/SystemZ/insn-ngr-01.s | 11 - test/MC/SystemZ/insn-ni-01.s | 17 - test/MC/SystemZ/insn-ni-02.s | 19 - test/MC/SystemZ/insn-nihf-01.s | 9 - test/MC/SystemZ/insn-nihf-02.s | 10 - test/MC/SystemZ/insn-nihh-01.s | 11 - test/MC/SystemZ/insn-nihh-02.s | 10 - test/MC/SystemZ/insn-nihl-01.s | 11 - test/MC/SystemZ/insn-nihl-02.s | 10 - test/MC/SystemZ/insn-nilf-01.s | 9 - test/MC/SystemZ/insn-nilf-02.s | 10 - test/MC/SystemZ/insn-nilh-01.s | 11 - test/MC/SystemZ/insn-nilh-02.s | 10 - test/MC/SystemZ/insn-nill-01.s | 11 - test/MC/SystemZ/insn-nill-02.s | 10 - test/MC/SystemZ/insn-niy-01.s | 23 - test/MC/SystemZ/insn-niy-02.s | 19 - test/MC/SystemZ/insn-nr-01.s | 11 - test/MC/SystemZ/insn-ny-01.s | 23 - test/MC/SystemZ/insn-ny-02.s | 10 - test/MC/SystemZ/insn-o-01.s | 17 - test/MC/SystemZ/insn-o-02.s | 10 - test/MC/SystemZ/insn-og-01.s | 23 - test/MC/SystemZ/insn-og-02.s | 10 - test/MC/SystemZ/insn-ogr-01.s | 11 - test/MC/SystemZ/insn-oi-01.s | 17 - test/MC/SystemZ/insn-oi-02.s | 19 - test/MC/SystemZ/insn-oihf-01.s | 9 - test/MC/SystemZ/insn-oihf-02.s | 10 - test/MC/SystemZ/insn-oihh-01.s | 11 - test/MC/SystemZ/insn-oihh-02.s | 10 - test/MC/SystemZ/insn-oihl-01.s | 11 - test/MC/SystemZ/insn-oihl-02.s | 10 - test/MC/SystemZ/insn-oilf-01.s | 9 - test/MC/SystemZ/insn-oilf-02.s | 10 - test/MC/SystemZ/insn-oilh-01.s | 11 - test/MC/SystemZ/insn-oilh-02.s | 10 - test/MC/SystemZ/insn-oill-01.s | 11 - test/MC/SystemZ/insn-oill-02.s | 10 - test/MC/SystemZ/insn-oiy-01.s | 23 - test/MC/SystemZ/insn-oiy-02.s | 19 - test/MC/SystemZ/insn-or-01.s | 11 - test/MC/SystemZ/insn-oy-01.s | 23 - test/MC/SystemZ/insn-oy-02.s | 10 - test/MC/SystemZ/insn-risbg-01.s | 17 - test/MC/SystemZ/insn-risbg-02.s | 22 - test/MC/SystemZ/insn-rll-01.s | 27 - test/MC/SystemZ/insn-rll-02.s | 16 - test/MC/SystemZ/insn-rllg-01.s | 27 - test/MC/SystemZ/insn-rllg-02.s | 16 - test/MC/SystemZ/insn-s-01.s | 17 - test/MC/SystemZ/insn-s-02.s | 10 - test/MC/SystemZ/insn-sdb-01.s | 17 - test/MC/SystemZ/insn-sdb-02.s | 10 - test/MC/SystemZ/insn-sdbr-01.s | 11 - test/MC/SystemZ/insn-seb-01.s | 17 - test/MC/SystemZ/insn-seb-02.s | 10 - test/MC/SystemZ/insn-sebr-01.s | 11 - test/MC/SystemZ/insn-sg-01.s | 23 - test/MC/SystemZ/insn-sg-02.s | 10 - test/MC/SystemZ/insn-sgf-01.s | 23 - test/MC/SystemZ/insn-sgf-02.s | 10 - test/MC/SystemZ/insn-sgfr-01.s | 11 - test/MC/SystemZ/insn-sgr-01.s | 11 - test/MC/SystemZ/insn-sl-01.s | 17 - test/MC/SystemZ/insn-sl-02.s | 10 - test/MC/SystemZ/insn-slb-01.s | 23 - test/MC/SystemZ/insn-slb-02.s | 10 - test/MC/SystemZ/insn-slbg-01.s | 23 - test/MC/SystemZ/insn-slbg-02.s | 10 - test/MC/SystemZ/insn-slbgr-01.s | 11 - test/MC/SystemZ/insn-slbr-01.s | 11 - test/MC/SystemZ/insn-slfi-01.s | 9 - test/MC/SystemZ/insn-slfi-02.s | 10 - test/MC/SystemZ/insn-slg-01.s | 23 - test/MC/SystemZ/insn-slg-02.s | 10 - test/MC/SystemZ/insn-slgf-01.s | 23 - test/MC/SystemZ/insn-slgf-02.s | 10 - test/MC/SystemZ/insn-slgfi-01.s | 9 - test/MC/SystemZ/insn-slgfi-02.s | 10 - test/MC/SystemZ/insn-slgfr-01.s | 11 - test/MC/SystemZ/insn-slgr-01.s | 11 - test/MC/SystemZ/insn-sll-01.s | 19 - test/MC/SystemZ/insn-sll-02.s | 16 - test/MC/SystemZ/insn-sllg-01.s | 27 - test/MC/SystemZ/insn-sllg-02.s | 16 - test/MC/SystemZ/insn-slr-01.s | 11 - test/MC/SystemZ/insn-sly-01.s | 23 - test/MC/SystemZ/insn-sly-02.s | 10 - test/MC/SystemZ/insn-sqdb-01.s | 17 - test/MC/SystemZ/insn-sqdb-02.s | 10 - test/MC/SystemZ/insn-sqdbr-01.s | 11 - test/MC/SystemZ/insn-sqeb-01.s | 17 - test/MC/SystemZ/insn-sqeb-02.s | 10 - test/MC/SystemZ/insn-sqebr-01.s | 11 - test/MC/SystemZ/insn-sqxbr-01.s | 11 - test/MC/SystemZ/insn-sqxbr-02.s | 17 - test/MC/SystemZ/insn-sr-01.s | 11 - test/MC/SystemZ/insn-sra-01.s | 19 - test/MC/SystemZ/insn-sra-02.s | 16 - test/MC/SystemZ/insn-srag-01.s | 27 - test/MC/SystemZ/insn-srag-02.s | 16 - test/MC/SystemZ/insn-srl-01.s | 19 - test/MC/SystemZ/insn-srl-02.s | 16 - test/MC/SystemZ/insn-srlg-01.s | 27 - test/MC/SystemZ/insn-srlg-02.s | 16 - test/MC/SystemZ/insn-st-01.s | 17 - test/MC/SystemZ/insn-st-02.s | 10 - test/MC/SystemZ/insn-stc-01.s | 17 - test/MC/SystemZ/insn-stc-02.s | 10 - test/MC/SystemZ/insn-stcy-01.s | 23 - test/MC/SystemZ/insn-stcy-02.s | 10 - test/MC/SystemZ/insn-std-01.s | 17 - test/MC/SystemZ/insn-std-02.s | 10 - test/MC/SystemZ/insn-stdy-01.s | 23 - test/MC/SystemZ/insn-stdy-02.s | 10 - test/MC/SystemZ/insn-ste-01.s | 17 - test/MC/SystemZ/insn-ste-02.s | 10 - test/MC/SystemZ/insn-stey-01.s | 23 - test/MC/SystemZ/insn-stey-02.s | 10 - test/MC/SystemZ/insn-stg-01.s | 23 - test/MC/SystemZ/insn-stg-02.s | 10 - test/MC/SystemZ/insn-stgrl-01.s | 31 - test/MC/SystemZ/insn-sth-01.s | 17 - test/MC/SystemZ/insn-sth-02.s | 10 - test/MC/SystemZ/insn-sthrl-01.s | 31 - test/MC/SystemZ/insn-sthy-01.s | 23 - test/MC/SystemZ/insn-sthy-02.s | 10 - test/MC/SystemZ/insn-stmg-01.s | 29 - test/MC/SystemZ/insn-stmg-02.s | 13 - test/MC/SystemZ/insn-strl-01.s | 31 - test/MC/SystemZ/insn-strv-01.s | 23 - test/MC/SystemZ/insn-strv-02.s | 10 - test/MC/SystemZ/insn-strvg-01.s | 23 - test/MC/SystemZ/insn-strvg-02.s | 10 - test/MC/SystemZ/insn-sty-01.s | 23 - test/MC/SystemZ/insn-sty-02.s | 10 - test/MC/SystemZ/insn-sxbr-01.s | 11 - test/MC/SystemZ/insn-sxbr-02.s | 17 - test/MC/SystemZ/insn-sy-01.s | 23 - test/MC/SystemZ/insn-sy-02.s | 10 - test/MC/SystemZ/insn-x-01.s | 17 - test/MC/SystemZ/insn-x-02.s | 10 - test/MC/SystemZ/insn-xg-01.s | 23 - test/MC/SystemZ/insn-xg-02.s | 10 - test/MC/SystemZ/insn-xgr-01.s | 11 - test/MC/SystemZ/insn-xi-01.s | 17 - test/MC/SystemZ/insn-xi-02.s | 19 - test/MC/SystemZ/insn-xihf-01.s | 9 - test/MC/SystemZ/insn-xihf-02.s | 10 - test/MC/SystemZ/insn-xilf-01.s | 9 - test/MC/SystemZ/insn-xilf-02.s | 10 - test/MC/SystemZ/insn-xiy-01.s | 23 - test/MC/SystemZ/insn-xiy-02.s | 19 - test/MC/SystemZ/insn-xr-01.s | 11 - test/MC/SystemZ/insn-xy-01.s | 23 - test/MC/SystemZ/insn-xy-02.s | 10 - test/MC/SystemZ/lit.local.cfg | 2 - test/MC/SystemZ/regs-01.s | 19 - test/MC/SystemZ/regs-02.s | 19 - test/MC/SystemZ/regs-03.s | 19 - test/MC/SystemZ/regs-04.s | 19 - test/MC/SystemZ/regs-05.s | 19 - test/MC/SystemZ/regs-06.s | 11 - test/MC/SystemZ/regs-07.s | 28 - test/MC/SystemZ/regs-08.s | 28 - test/MC/SystemZ/regs-09.s | 31 - test/MC/SystemZ/regs-10.s | 28 - test/MC/SystemZ/regs-11.s | 28 - test/MC/SystemZ/regs-12.s | 31 - test/MC/SystemZ/regs-13.s | 69 - test/MC/SystemZ/regs-14.s | 18 - test/MC/SystemZ/regs-15.s | 19 - test/MC/SystemZ/regs-bad.s | 267 + test/MC/SystemZ/regs-good.s | 169 + test/MC/SystemZ/tokens.s | 79 + .../AlignedBundling/align-mode-argument-error.s | 2 +- .../AlignedBundling/bundle-group-too-large-error.s | 2 +- .../X86/AlignedBundling/bundle-lock-option-error.s | 2 +- test/MC/X86/AlignedBundling/lit.local.cfg | 2 - .../lock-without-bundle-mode-error.s | 2 +- .../AlignedBundling/switch-section-locked-error.s | 2 +- .../AlignedBundling/unlock-without-lock-error.s | 2 +- test/MC/X86/avx512-encodings.s | 45 + test/MC/X86/cfi_def_cfa-crash.s | 73 + test/MC/X86/intel-syntax.s | 261 + test/MC/X86/lit.local.cfg | 2 - test/MC/X86/x86-32-coverage.s | 38 +- test/MC/X86/x86-32.s | 6 +- test/MC/X86/x86-64.s | 232 +- test/MC/X86/x86_64-avx-encoding.s | 80 +- test/MC/X86/x86_64-encoding.s | 72 + test/MC/X86/x86_64-hle-encoding.s | 9 + test/MC/X86/x86_64-tbm-encoding.s | 196 + test/MC/X86/x86_errors.s | 3 + test/MC/X86/x86_nop.s | 43 +- test/Makefile | 28 +- test/Makefile.tests | 12 - test/Object/ARM/macho-data-in-code.test | 7 + test/Object/Inputs/COFF/i386.yaml | 6 +- test/Object/Inputs/COFF/x86-64.yaml | 6 +- test/Object/Inputs/ELF/BE32.yaml | 6 + test/Object/Inputs/ELF/BE64.yaml | 6 + test/Object/Inputs/ELF/LE32.yaml | 6 + test/Object/Inputs/ELF/LE64.yaml | 6 + test/Object/Inputs/GNU.a | Bin 0 -> 4210 bytes test/Object/Inputs/IsNAN.o | Bin 0 -> 2280 bytes test/Object/Inputs/MacOSX.a | Bin 0 -> 4166 bytes test/Object/Inputs/SVR4.a | Bin 0 -> 4214 bytes .../Inputs/archive-test.a-corrupt-symbol-table | Bin 0 -> 2792 bytes test/Object/Inputs/archive-test.a-empty | 1 + test/Object/Inputs/archive-test.a-gnu-minimal | 2 + test/Object/Inputs/archive-test.a-gnu-no-symtab | 5 + test/Object/Inputs/coff_archive_short.lib | Bin 0 -> 1336 bytes test/Object/Inputs/corrupt-version.elf-x86_64 | Bin 0 -> 5200 bytes test/Object/Inputs/corrupt.elf-x86-64 | Bin 0 -> 1024 bytes test/Object/Inputs/elf-reloc-no-sym.x86_64 | Bin 0 -> 1768 bytes test/Object/Inputs/evenlen | 1 + .../Object/Inputs/macho-data-in-code.macho-thumbv7 | Bin 0 -> 680 bytes test/Object/Inputs/macho-universal.x86_64.i386 | Bin 0 -> 16624 bytes test/Object/Inputs/oddlen | 1 + test/Object/Inputs/program-headers.mips | Bin 0 -> 648 bytes .../Inputs/trivial-executable-test.macho-x86-64 | Bin 0 -> 8512 bytes test/Object/Inputs/trivial-object-test2.elf-x86-64 | Bin 0 -> 1424 bytes test/Object/Inputs/very_long_bytecode_file_name.bc | Bin 0 -> 1465 bytes test/Object/Inputs/weak-global-symbol.macho-i386 | Bin 0 -> 344 bytes test/Object/Inputs/xpg4.a | Bin 0 -> 4214 bytes test/Object/Mips/lit.local.cfg | 2 - test/Object/X86/lit.local.cfg | 2 - test/Object/X86/objdump-cfg-invalid-opcode.yaml | 58 + test/Object/X86/objdump-cfg-textatomsize.yaml | 39 + test/Object/X86/objdump-cfg.yaml | 86 + .../objdump-disassembly-inline-relocations.test | 35 + test/Object/X86/objdump-disassembly-symbolic.test | 48 + test/Object/ar-create.test | 17 + test/Object/archive-delete.test | 30 + test/Object/archive-error-tmp.txt | 9 + test/Object/archive-extract-dir.test | 13 + test/Object/archive-format.test | 22 + test/Object/archive-move.test | 50 + test/Object/archive-replace-pos.test | 30 + test/Object/archive-symtab.test | 59 + test/Object/archive-toc.test | 28 + test/Object/archive-update.test | 37 + test/Object/check_binary_output.ll | 4 + test/Object/coff-archive-short.test | 26 + test/Object/corrupt.test | 24 + test/Object/directory.ll | 13 + test/Object/elf-reloc-no-sym.test | 7 + test/Object/extract.ll | 46 + test/Object/lit.local.cfg | 2 +- test/Object/nm-archive.test | 25 +- test/Object/nm-error.test | 17 + test/Object/nm-trivial-object.test | 9 +- test/Object/nm-universal-binary.test | 6 + test/Object/nm-weak-global-macho.test | 3 + test/Object/obj2yaml.test | 187 +- test/Object/relocation-executable.test | 14 +- test/Object/yaml2obj-elf-bits-endian.test | 16 + test/Object/yaml2obj-elf-file-headers.yaml | 11 + test/Object/yaml2obj-elf-section-basic.yaml | 35 + .../yaml2obj-elf-symbol-LocalGlobalWeak.yaml | 37 + test/Object/yaml2obj-elf-symbol-basic.yaml | 40 + test/Other/Inputs/TestProg/TestProg | 3 + test/Other/Inputs/llvm-cov.gcda | Bin 296 -> 0 bytes test/Other/Inputs/llvm-cov.gcno | Bin 984 -> 0 bytes test/Other/Inputs/llvm_cov.gcda | Bin 0 -> 296 bytes test/Other/Inputs/llvm_cov.gcno | Bin 0 -> 984 bytes test/Other/ResponseFile.ll | 8 +- test/Other/X86/lit.local.cfg | 2 - test/Other/attribute-comment.ll | 2 +- test/Other/can-execute.txt | 20 + test/Other/close-stderr.ll | 3 - test/Other/constant-fold-gep-address-spaces.ll | 235 + test/Other/constant-fold-gep.ll | 4 +- test/Other/extract-alias.ll | 2 +- test/Other/extract-linkonce.ll | 11 +- test/Other/lit.local.cfg | 1 - test/Other/llvm-cov.test | 5 +- test/Other/optimize-options.ll | 12 +- test/Other/pipefail.txt | 2 + test/Other/umask.ll | 14 + test/TableGen/2003-08-03-PassCode.td | 1 - test/TableGen/2006-09-18-LargeInt.td | 4 +- test/TableGen/2010-03-24-PrematureDefaults.td | 1 + test/TableGen/CStyleComment.td | 1 - test/TableGen/Dag.td | 1 + test/TableGen/DefmInherit.td | 9 +- test/TableGen/DefmInsideMultiClass.td | 6 +- test/TableGen/ForeachList.td | 1 + test/TableGen/ForeachLoop.td | 1 + test/TableGen/Include.td | 2 +- test/TableGen/IntBitInit.td | 2 +- test/TableGen/LazyChange.td | 4 +- test/TableGen/LetInsideMultiClasses.td | 8 +- test/TableGen/ListOfList.td | 6 +- test/TableGen/LoLoL.td | 1 + test/TableGen/MultiClass.td | 7 +- test/TableGen/MultiClassDefName.td | 6 +- test/TableGen/MultiClassInherit.td | 34 +- test/TableGen/MultiPat.td | 1 + test/TableGen/NestedForeach.td | 1 + test/TableGen/Paste.td | 1 + test/TableGen/SetTheory.td | 1 + test/TableGen/SiblingForeach.td | 1 + test/TableGen/Slice.td | 1 + test/TableGen/String.td | 2 +- test/TableGen/TargetInstrSpec.td | 10 +- test/TableGen/TwoLevelName.td | 1 + test/TableGen/cast.td | 8 +- test/TableGen/defmclass.td | 1 + test/TableGen/eq.td | 1 + test/TableGen/eqbit.td | 1 + test/TableGen/foreach.td | 14 +- test/TableGen/if.td | 1 + test/TableGen/ifbit.td | 1 + test/TableGen/intrinsic-order.td | 36 + test/TableGen/intrinsic-varargs.td | 30 + test/TableGen/lisp.td | 18 +- test/TableGen/list-element-bitref.td | 1 + test/TableGen/math.td | 1 + test/TableGen/nested-comment.td | 1 - test/TableGen/pr8330.td | 1 + test/TableGen/strconcat.td | 4 +- test/TableGen/subst.td | 61 +- test/TableGen/subst2.td | 1 + test/TableGen/usevalname.td | 1 + test/Transforms/ADCE/lit.local.cfg | 1 - test/Transforms/ArgumentPromotion/lit.local.cfg | 1 - test/Transforms/ArgumentPromotion/reserve-tbaa.ll | 52 + test/Transforms/BBVectorize/X86/cmp-types.ll | 2 +- test/Transforms/BBVectorize/X86/loop1.ll | 4 +- test/Transforms/BBVectorize/X86/pr15289.ll | 23 +- test/Transforms/BBVectorize/X86/sh-rec.ll | 2 +- test/Transforms/BBVectorize/X86/sh-rec2.ll | 2 +- test/Transforms/BBVectorize/X86/sh-rec3.ll | 2 +- test/Transforms/BBVectorize/X86/sh-types.ll | 2 +- test/Transforms/BBVectorize/X86/simple-int.ll | 10 +- test/Transforms/BBVectorize/X86/simple-ldstr.ll | 2 +- test/Transforms/BBVectorize/X86/simple.ll | 10 +- test/Transforms/BBVectorize/X86/vs-cast.ll | 2 +- test/Transforms/BBVectorize/X86/wr-aliases.ll | 144 + test/Transforms/BBVectorize/cycle.ll | 2 +- test/Transforms/BBVectorize/ld1.ll | 2 +- test/Transforms/BBVectorize/lit.local.cfg | 2 - test/Transforms/BBVectorize/loop1.ll | 4 +- test/Transforms/BBVectorize/mem-op-depth.ll | 2 +- test/Transforms/BBVectorize/metadata.ll | 4 +- test/Transforms/BBVectorize/no-ldstr-conn.ll | 2 +- test/Transforms/BBVectorize/req-depth.ll | 4 +- test/Transforms/BBVectorize/search-limit.ll | 4 +- test/Transforms/BBVectorize/simple-int.ll | 10 +- test/Transforms/BBVectorize/simple-ldstr-ptrs.ll | 12 +- test/Transforms/BBVectorize/simple-ldstr.ll | 20 +- test/Transforms/BBVectorize/simple-sel.ll | 6 +- test/Transforms/BBVectorize/simple-tst.ll | 2 +- test/Transforms/BBVectorize/simple.ll | 16 +- test/Transforms/BBVectorize/simple3.ll | 2 +- .../BBVectorize/xcore/no-vector-registers.ll | 18 + test/Transforms/BlockPlacement/basictest.ll | 15 - test/Transforms/BlockPlacement/lit.local.cfg | 1 - test/Transforms/CodeExtractor/lit.local.cfg | 1 - test/Transforms/CodeGenPrepare/basic.ll | 2 +- test/Transforms/CodeGenPrepare/lit.local.cfg | 1 - test/Transforms/ConstProp/basictest.ll | 10 +- test/Transforms/ConstProp/bitcast.ll | 2 +- test/Transforms/ConstProp/bswap.ll | 8 +- test/Transforms/ConstProp/calls.ll | 24 +- test/Transforms/ConstProp/extractvalue.ll | 6 +- test/Transforms/ConstProp/insertvalue.ll | 6 +- test/Transforms/ConstProp/lit.local.cfg | 1 - test/Transforms/ConstProp/loads.ll | 76 +- test/Transforms/ConstProp/overflow-ops.ll | 38 +- test/Transforms/ConstantMerge/align.ll | 28 + test/Transforms/ConstantMerge/lit.local.cfg | 1 - .../CorrelatedValuePropagation/2010-09-02-Trunc.ll | 4 +- .../Transforms/CorrelatedValuePropagation/basic.ll | 18 +- .../CorrelatedValuePropagation/lit.local.cfg | 1 - .../Transforms/CorrelatedValuePropagation/range.ll | 14 +- test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll | 33 +- .../2013-05-17-VarargsAndBlockAddress.ll | 25 + test/Transforms/DeadArgElim/dbginfo.ll | 18 +- test/Transforms/DeadArgElim/deadexternal.ll | 2 +- test/Transforms/DeadArgElim/keepalive.ll | 2 +- test/Transforms/DeadArgElim/linkage.ll | 21 + test/Transforms/DeadArgElim/lit.local.cfg | 1 - test/Transforms/DeadArgElim/returned.ll | 55 + test/Transforms/DeadArgElim/variadic_safety.ll | 38 + .../2011-09-06-EndOfFunction.ll | 2 +- .../DeadStoreElimination/OverwriteStoreEnd.ll | 14 +- .../DeadStoreElimination/PartialStore.ll | 10 +- .../DeadStoreElimination/const-pointers.ll | 6 +- test/Transforms/DeadStoreElimination/free.ll | 10 +- .../Transforms/DeadStoreElimination/inst-limits.ll | 261 + test/Transforms/DeadStoreElimination/libcalls.ll | 12 +- test/Transforms/DeadStoreElimination/lifetime.ll | 2 +- test/Transforms/DeadStoreElimination/lit.local.cfg | 1 - .../DeadStoreElimination/memintrinsics.ll | 6 +- .../DeadStoreElimination/no-targetdata.ll | 2 +- test/Transforms/DeadStoreElimination/simple.ll | 50 +- test/Transforms/DebugIR/crash.ll | 42 + test/Transforms/DebugIR/exception.ll | 127 + test/Transforms/DebugIR/function.ll | 51 + test/Transforms/DebugIR/simple-addrspace.ll | 13 + test/Transforms/DebugIR/simple.ll | 25 + test/Transforms/DebugIR/struct.ll | 24 + test/Transforms/DebugIR/vector.ll | 93 + test/Transforms/EarlyCSE/basic.ll | 16 +- test/Transforms/EarlyCSE/commute.ll | 10 +- test/Transforms/EarlyCSE/instsimplify-dom.ll | 2 +- test/Transforms/EarlyCSE/lit.local.cfg | 1 - .../FunctionAttrs/2009-01-02-LocalStores.ll | 13 +- .../FunctionAttrs/2009-01-04-Annotate.ll | 2 +- test/Transforms/FunctionAttrs/annotate-1.ll | 7 +- test/Transforms/FunctionAttrs/atomic.ll | 2 +- test/Transforms/FunctionAttrs/lit.local.cfg | 1 - test/Transforms/FunctionAttrs/nocapture.ll | 20 +- test/Transforms/FunctionAttrs/noreturn.ll | 2 +- test/Transforms/FunctionAttrs/readattrs.ll | 47 + test/Transforms/GCOVProfiling/linkagename.ll | 6 +- test/Transforms/GCOVProfiling/lit.local.cfg | 1 - test/Transforms/GCOVProfiling/version.ll | 15 +- .../Transforms/GVN/2007-07-26-InterlockingLoops.ll | 8 +- test/Transforms/GVN/2008-07-02-Unreachable.ll | 8 +- test/Transforms/GVN/2010-11-13-Simplify.ll | 2 +- .../GVN/2011-06-01-NonLocalMemdepMiscompile.ll | 6 +- .../GVN/2011-07-07-MatchIntrinsicExtract.ll | 12 +- test/Transforms/GVN/commute.ll | 4 +- test/Transforms/GVN/cond_br.ll | 55 + test/Transforms/GVN/cond_br2.ll | 140 + test/Transforms/GVN/condprop.ll | 22 +- test/Transforms/GVN/edge.ll | 8 +- test/Transforms/GVN/lit.local.cfg | 1 - test/Transforms/GVN/load-pre-align.ll | 2 +- test/Transforms/GVN/local-pre.ll | 6 +- test/Transforms/GVN/malloc-load-removal.ll | 31 +- test/Transforms/GVN/non-local-offset.ll | 4 +- test/Transforms/GVN/phi-translate.ll | 2 +- test/Transforms/GVN/pr14166.ll | 2 +- test/Transforms/GVN/pr17732.ll | 30 + test/Transforms/GVN/pr17852.ll | 66 + test/Transforms/GVN/pre-load.ll | 16 +- test/Transforms/GVN/preserve-tbaa.ll | 5 +- test/Transforms/GVN/readattrs.ll | 17 + test/Transforms/GVN/rle-nonlocal.ll | 5 +- test/Transforms/GVN/rle-phi-translate.ll | 10 +- test/Transforms/GVN/rle-semidominated.ll | 5 +- test/Transforms/GVN/rle.ll | 92 +- test/Transforms/GVN/tbaa.ll | 28 +- test/Transforms/GlobalDCE/lit.local.cfg | 1 - test/Transforms/GlobalOpt/2008-07-17-addrspace.ll | 2 +- .../GlobalOpt/2009-02-15-ResolveAlias.ll | 2 +- test/Transforms/GlobalOpt/2009-03-05-dbg.ll | 18 +- .../GlobalOpt/2012-05-11-blockaddress.ll | 2 +- test/Transforms/GlobalOpt/alias-resolve.ll | 35 +- test/Transforms/GlobalOpt/alias-used.ll | 13 +- test/Transforms/GlobalOpt/array-elem-refs.ll | 32 + test/Transforms/GlobalOpt/atexit.ll | 6 + test/Transforms/GlobalOpt/atomic.ll | 15 + test/Transforms/GlobalOpt/blockaddress.ll | 4 +- .../GlobalOpt/cleanup-pointer-root-users.ll | 8 +- test/Transforms/GlobalOpt/compiler-used.ll | 16 + .../GlobalOpt/ctor-list-opt-constexpr.ll | 4 +- test/Transforms/GlobalOpt/deadglobal.ll | 2 +- test/Transforms/GlobalOpt/integer-bool.ll | 2 +- .../Transforms/GlobalOpt/invariant-nodatalayout.ll | 17 + test/Transforms/GlobalOpt/lit.local.cfg | 1 - test/Transforms/GlobalOpt/load-store-global.ll | 6 +- test/Transforms/GlobalOpt/malloc-promote-3.ll | 18 + test/Transforms/GlobalOpt/metadata.ll | 2 +- test/Transforms/GlobalOpt/tls.ll | 4 +- .../GlobalOpt/zeroinitializer-gep-load.ll | 2 +- test/Transforms/IPConstantProp/lit.local.cfg | 1 - .../IndVarSimplify/2011-10-27-lftrnull.ll | 2 +- .../IndVarSimplify/2011-11-01-lftrptr.ll | 8 +- .../IndVarSimplify/2011-11-17-selfphi.ll | 2 +- .../IndVarSimplify/2012-07-17-lftr-undef.ll | 2 +- .../2012-10-19-congruent-constant.ll | 2 +- test/Transforms/IndVarSimplify/dont-recompute.ll | 4 +- .../IndVarSimplify/eliminate-comparison.ll | 10 +- test/Transforms/IndVarSimplify/eliminate-rem.ll | 4 +- .../Transforms/IndVarSimplify/floating-point-iv.ll | 10 +- test/Transforms/IndVarSimplify/iv-fold.ll | 4 +- .../IndVarSimplify/lftr-address-space-pointers.ll | 69 + .../Transforms/IndVarSimplify/lftr-extend-const.ll | 44 + test/Transforms/IndVarSimplify/lftr-reuse.ll | 4 +- test/Transforms/IndVarSimplify/lftr-zext.ll | 26 + test/Transforms/IndVarSimplify/lit.local.cfg | 1 - test/Transforms/IndVarSimplify/loop_evaluate_1.ll | 34 +- test/Transforms/IndVarSimplify/loop_evaluate_6.ll | 5 - test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 9 +- .../Transforms/IndVarSimplify/tripcount_compute.ll | 14 +- .../IndVarSimplify/udiv-invariant-but-traps.ll | 32 + test/Transforms/IndVarSimplify/udiv.ll | 4 +- test/Transforms/IndVarSimplify/ult-sub-to-eq.ll | 2 +- test/Transforms/IndVarSimplify/widen-nsw.ll | 29 + test/Transforms/Inline/2010-05-31-ByvalTailcall.ll | 2 +- test/Transforms/Inline/alloca-bonus.ll | 10 +- test/Transforms/Inline/alloca-merge-align-nodl.ll | 88 + test/Transforms/Inline/alloca-merge-align.ll | 122 + test/Transforms/Inline/always-inline.ll | 14 +- test/Transforms/Inline/attributes.ll | 112 + test/Transforms/Inline/basictest.ll | 8 +- test/Transforms/Inline/byval.ll | 23 + test/Transforms/Inline/delete-call.ll | 2 +- test/Transforms/Inline/devirtualize-2.ll | 2 +- test/Transforms/Inline/devirtualize.ll | 2 +- test/Transforms/Inline/dynamic_alloca_test.ll | 2 +- test/Transforms/Inline/gvn-inline-iteration.ll | 4 +- test/Transforms/Inline/inline-byval-bonus.ll | 2 +- .../Inline/inline-invoke-with-asm-call.ll | 32 + test/Transforms/Inline/inline-optnone.ll | 52 + test/Transforms/Inline/inline_cleanup.ll | 8 +- test/Transforms/Inline/inline_constprop.ll | 41 +- test/Transforms/Inline/inline_minisize.ll | 4 +- test/Transforms/Inline/inline_returns_twice.ll | 71 +- test/Transforms/Inline/invoke-cost.ll | 45 + test/Transforms/Inline/lifetime-no-datalayout.ll | 2 +- test/Transforms/Inline/lifetime.ll | 8 +- test/Transforms/Inline/lit.local.cfg | 1 - test/Transforms/Inline/nested-inline.ll | 6 +- test/Transforms/Inline/noinline-recursive-fn.ll | 6 +- test/Transforms/Inline/ptr-diff.ll | 49 +- test/Transforms/Inline/recursive.ll | 4 +- .../InstCombine/2002-05-14-SubFailure.ll | 5 +- .../InstCombine/2002-12-05-MissedConstProp.ll | 4 +- .../InstCombine/2003-08-12-AllocaNonNull.ll | 5 +- test/Transforms/InstCombine/2006-10-20-mask.ll | 4 +- .../InstCombine/2006-10-26-VectorReassoc.ll | 5 +- .../InstCombine/2006-12-08-Select-ICmp.ll | 3 +- test/Transforms/InstCombine/2007-01-27-AndICmp.ll | 4 +- .../InstCombine/2008-01-06-BitCastAttributes.ll | 25 +- test/Transforms/InstCombine/2008-01-06-VoidCast.ll | 10 +- .../InstCombine/2008-01-27-FloatSelect.ll | 3 +- test/Transforms/InstCombine/2008-02-13-MulURem.ll | 4 +- test/Transforms/InstCombine/2008-05-31-AddBool.ll | 4 +- .../Transforms/InstCombine/2008-11-20-DivMulRem.ll | 12 +- .../InstCombine/2009-01-16-PointerAddrSpace.ll | 2 +- test/Transforms/InstCombine/2010-03-03-ExtElim.ll | 20 +- .../Transforms/InstCombine/2010-11-01-lshr-mask.ll | 4 +- .../InstCombine/2010-11-21-SizeZeroTypeGEP.ll | 4 +- .../InstCombine/2010-11-23-Distributed.ll | 4 +- .../InstCombine/2011-06-13-nsw-alloca.ll | 4 +- .../InstCombine/2012-03-10-InstCombine.ll | 2 +- test/Transforms/InstCombine/2012-04-24-vselect.ll | 2 +- .../InstCombine/2012-05-28-select-hang.ll | 2 +- .../InstCombine/2012-07-30-addrsp-bitcast.ll | 4 +- .../Transforms/InstCombine/2012-08-28-udiv_ashl.ll | 8 +- .../InstCombine/2012-09-17-ZeroSizedAlloca.ll | 2 +- .../2012-09-24-MemcpyFromGlobalCrash.ll | 2 +- .../InstCombine/2012-3-15-or-xor-constant.ll | 2 +- .../2013-03-05-Combine-BitcastTy-Into-Alloca.ll | 2 +- test/Transforms/InstCombine/ExtractCast.ll | 4 +- test/Transforms/InstCombine/LandingPadClauses.ll | 6 +- test/Transforms/InstCombine/PR7357.ll | 17 + test/Transforms/InstCombine/abs-1.ll | 6 +- test/Transforms/InstCombine/add2.ll | 8 +- test/Transforms/InstCombine/add4.ll | 45 +- test/Transforms/InstCombine/addrspacecast.ll | 69 + test/Transforms/InstCombine/align-addr.ll | 31 +- test/Transforms/InstCombine/align-external.ll | 2 +- test/Transforms/InstCombine/alloca.ll | 37 +- test/Transforms/InstCombine/and-xor-or.ll | 4 +- test/Transforms/InstCombine/and.ll | 6 +- test/Transforms/InstCombine/and2.ll | 18 +- .../InstCombine/apint-call-cast-target.ll | 7 +- test/Transforms/InstCombine/apint-select.ll | 5 +- .../Transforms/InstCombine/apint-shift-simplify.ll | 6 +- test/Transforms/InstCombine/apint-shift.ll | 60 +- test/Transforms/InstCombine/apint-shl-trunc.ll | 4 +- test/Transforms/InstCombine/atomic.ll | 4 +- test/Transforms/InstCombine/badmalloc.ll | 4 +- .../InstCombine/bitcast-alias-function.ll | 229 + test/Transforms/InstCombine/bitcast-bigendian.ll | 45 +- test/Transforms/InstCombine/bitcast-vec-uniform.ll | 16 +- test/Transforms/InstCombine/bitcast-vector-fold.ll | 2 +- test/Transforms/InstCombine/bitcast.ll | 32 +- test/Transforms/InstCombine/call-cast-target.ll | 9 +- test/Transforms/InstCombine/call.ll | 222 +- test/Transforms/InstCombine/canonicalize_branch.ll | 8 +- test/Transforms/InstCombine/cast.ll | 147 +- test/Transforms/InstCombine/cast_ptr.ll | 55 +- test/Transforms/InstCombine/compare-signs.ll | 12 +- .../constant-fold-address-space-pointer.ll | 232 + test/Transforms/InstCombine/constant-fold-gep.ll | 22 +- test/Transforms/InstCombine/cos-1.ll | 6 +- test/Transforms/InstCombine/cos-2.ll | 2 +- test/Transforms/InstCombine/debug-line.ll | 16 +- test/Transforms/InstCombine/debuginfo.ll | 27 +- .../InstCombine/disable-simplify-libcalls.ll | 74 +- test/Transforms/InstCombine/div-shift-crash.ll | 101 + test/Transforms/InstCombine/div-shift.ll | 38 + test/Transforms/InstCombine/div.ll | 30 +- .../InstCombine/double-float-shrink-1.ll | 13 + .../InstCombine/enforce-known-alignment.ll | 26 +- test/Transforms/InstCombine/err-rep-cold.ll | 77 + test/Transforms/InstCombine/exact.ll | 36 +- test/Transforms/InstCombine/exp2-1.ll | 16 +- test/Transforms/InstCombine/exp2-2.ll | 2 +- test/Transforms/InstCombine/extractvalue.ll | 6 +- test/Transforms/InstCombine/fast-math.ll | 84 +- test/Transforms/InstCombine/fcmp.ll | 32 +- test/Transforms/InstCombine/fdiv.ll | 6 +- test/Transforms/InstCombine/ffs-1.ll | 32 +- .../Transforms/InstCombine/float-shrink-compare.ll | 179 + test/Transforms/InstCombine/fmul.ll | 37 +- test/Transforms/InstCombine/fneg-ext.ll | 23 + test/Transforms/InstCombine/fold-bin-operand.ll | 4 +- test/Transforms/InstCombine/fold-calls.ll | 4 +- .../InstCombine/fold-fops-into-selects.ll | 71 + test/Transforms/InstCombine/fold-vector-select.ll | 4 +- test/Transforms/InstCombine/fpcast.ll | 12 + test/Transforms/InstCombine/fprintf-1.ll | 16 +- test/Transforms/InstCombine/fputs-1.ll | 6 +- test/Transforms/InstCombine/fwrite-1.ll | 10 +- test/Transforms/InstCombine/gep-addrspace.ll | 2 +- test/Transforms/InstCombine/getelementptr.ll | 438 +- test/Transforms/InstCombine/icmp-logical.ll | 152 + test/Transforms/InstCombine/icmp.ll | 604 +- test/Transforms/InstCombine/idioms.ll | 2 +- test/Transforms/InstCombine/intrinsics.ll | 40 +- test/Transforms/InstCombine/invoke.ll | 6 +- test/Transforms/InstCombine/isascii-1.ll | 6 +- test/Transforms/InstCombine/isdigit-1.ll | 10 +- test/Transforms/InstCombine/lit.local.cfg | 1 - test/Transforms/InstCombine/load-cmp.ll | 334 +- test/Transforms/InstCombine/load-select.ll | 2 +- test/Transforms/InstCombine/load3.ll | 6 +- test/Transforms/InstCombine/malloc-free-delete.ll | 36 +- test/Transforms/InstCombine/memcmp-1.ll | 12 +- test/Transforms/InstCombine/memcmp-2.ll | 2 +- test/Transforms/InstCombine/memcpy-1.ll | 2 +- test/Transforms/InstCombine/memcpy-2.ll | 2 +- test/Transforms/InstCombine/memcpy-from-global.ll | 18 +- test/Transforms/InstCombine/memcpy.ll | 6 +- test/Transforms/InstCombine/memcpy_chk-1.ll | 8 +- test/Transforms/InstCombine/memcpy_chk-2.ll | 2 +- test/Transforms/InstCombine/memmove-1.ll | 2 +- test/Transforms/InstCombine/memmove-2.ll | 2 +- test/Transforms/InstCombine/memmove_chk-1.ll | 8 +- test/Transforms/InstCombine/memmove_chk-2.ll | 2 +- test/Transforms/InstCombine/memset-1.ll | 2 +- test/Transforms/InstCombine/memset-2.ll | 2 +- test/Transforms/InstCombine/memset_chk-1.ll | 10 +- test/Transforms/InstCombine/memset_chk-2.ll | 2 +- test/Transforms/InstCombine/merge-icmp.ll | 4 +- test/Transforms/InstCombine/mul.ll | 38 +- .../multi-size-address-space-pointer.ll | 112 + test/Transforms/InstCombine/no-negzero.ll | 2 +- test/Transforms/InstCombine/nsw.ll | 18 +- test/Transforms/InstCombine/objsize-64.ll | 4 +- .../InstCombine/objsize-address-space.ll | 80 + test/Transforms/InstCombine/objsize.ll | 92 +- test/Transforms/InstCombine/onehot_merge.ll | 35 + test/Transforms/InstCombine/or-fcmp.ll | 10 +- test/Transforms/InstCombine/or-xor.ll | 18 +- test/Transforms/InstCombine/or.ll | 78 +- test/Transforms/InstCombine/osx-names.ll | 4 +- test/Transforms/InstCombine/overflow.ll | 14 +- .../Transforms/InstCombine/phi-select-constexpr.ll | 19 + test/Transforms/InstCombine/phi.ll | 54 +- test/Transforms/InstCombine/pow-1.ll | 45 +- test/Transforms/InstCombine/pow-2.ll | 2 +- test/Transforms/InstCombine/pow-3.ll | 12 + test/Transforms/InstCombine/pr17827.ll | 74 + test/Transforms/InstCombine/pr8547.ll | 2 +- test/Transforms/InstCombine/printf-1.ll | 22 +- test/Transforms/InstCombine/printf-2.ll | 6 +- test/Transforms/InstCombine/ptr-int-cast.ll | 8 +- test/Transforms/InstCombine/puts-1.ll | 4 +- test/Transforms/InstCombine/rem.ll | 122 +- test/Transforms/InstCombine/select-2.ll | 5 +- test/Transforms/InstCombine/select-crash.ll | 4 +- .../InstCombine/select-extractelement.ll | 102 + test/Transforms/InstCombine/select.ll | 220 +- test/Transforms/InstCombine/sext.ll | 34 +- test/Transforms/InstCombine/shift-sra.ll | 10 +- test/Transforms/InstCombine/shift.ll | 187 +- test/Transforms/InstCombine/sign-test-and-or.ll | 18 +- test/Transforms/InstCombine/signext.ll | 16 +- test/Transforms/InstCombine/simplify-libcalls.ll | 144 + test/Transforms/InstCombine/sincospi.ll | 91 + test/Transforms/InstCombine/sink_instruction.ll | 4 +- test/Transforms/InstCombine/sprintf-1.ll | 18 +- test/Transforms/InstCombine/sqrt.ll | 6 +- test/Transforms/InstCombine/store.ll | 15 +- test/Transforms/InstCombine/stpcpy-1.ll | 6 +- test/Transforms/InstCombine/stpcpy-2.ll | 2 +- test/Transforms/InstCombine/stpcpy_chk-1.ll | 20 +- test/Transforms/InstCombine/stpcpy_chk-2.ll | 2 +- test/Transforms/InstCombine/strcat-1.ll | 2 +- test/Transforms/InstCombine/strcat-2.ll | 4 +- test/Transforms/InstCombine/strcat-3.ll | 2 +- test/Transforms/InstCombine/strchr-1.ll | 11 + test/Transforms/InstCombine/strcmp-1.ll | 12 +- test/Transforms/InstCombine/strcmp-2.ll | 2 +- test/Transforms/InstCombine/strcpy-1.ll | 6 +- test/Transforms/InstCombine/strcpy-2.ll | 2 +- test/Transforms/InstCombine/strcpy_chk-1.ll | 20 +- test/Transforms/InstCombine/strcpy_chk-2.ll | 2 +- test/Transforms/InstCombine/strcpy_chk-64.ll | 2 +- test/Transforms/InstCombine/strcspn-1.ll | 8 +- test/Transforms/InstCombine/strcspn-2.ll | 2 +- test/Transforms/InstCombine/strlen-1.ll | 18 +- test/Transforms/InstCombine/strlen-2.ll | 2 +- test/Transforms/InstCombine/strncat-1.ll | 2 +- test/Transforms/InstCombine/strncat-2.ll | 8 +- test/Transforms/InstCombine/strncat-3.ll | 2 +- test/Transforms/InstCombine/strncmp-1.ll | 16 +- test/Transforms/InstCombine/strncmp-2.ll | 2 +- test/Transforms/InstCombine/strncpy-1.ll | 12 +- test/Transforms/InstCombine/strncpy-2.ll | 2 +- test/Transforms/InstCombine/strncpy_chk-1.ll | 10 +- test/Transforms/InstCombine/strncpy_chk-2.ll | 2 +- test/Transforms/InstCombine/strpbrk-1.ll | 10 +- test/Transforms/InstCombine/strpbrk-2.ll | 2 +- test/Transforms/InstCombine/strrchr-1.ll | 13 +- test/Transforms/InstCombine/strspn-1.ll | 8 +- test/Transforms/InstCombine/strstr-1.ll | 10 +- test/Transforms/InstCombine/strstr-2.ll | 2 +- test/Transforms/InstCombine/strto-1.ll | 30 +- test/Transforms/InstCombine/struct-assign-tbaa.ll | 8 +- test/Transforms/InstCombine/sub-xor.ll | 8 +- test/Transforms/InstCombine/sub.ll | 237 +- test/Transforms/InstCombine/toascii-1.ll | 14 +- test/Transforms/InstCombine/trunc.ll | 20 +- .../Transforms/InstCombine/udivrem-change-width.ll | 12 +- test/Transforms/InstCombine/vec_demanded_elts.ll | 18 +- test/Transforms/InstCombine/vec_extract_elt.ll | 3 +- test/Transforms/InstCombine/vec_insertelt.ll | 3 +- test/Transforms/InstCombine/vec_phi_extract.ll | 25 + test/Transforms/InstCombine/vec_shuffle.ll | 105 +- test/Transforms/InstCombine/vector-casts.ll | 12 +- test/Transforms/InstCombine/vector-mul.ll | 408 + test/Transforms/InstCombine/vector_gep2.ll | 2 +- test/Transforms/InstCombine/weak-symbols.ll | 4 +- test/Transforms/InstCombine/win-math.ll | 295 + test/Transforms/InstCombine/xor2.ll | 14 +- test/Transforms/InstCombine/zext-bool-add-sub.ll | 2 +- test/Transforms/InstSimplify/2010-12-20-Boolean.ll | 8 +- .../InstSimplify/2010-12-20-Distribute.ll | 12 +- test/Transforms/InstSimplify/2011-01-14-Thread.ll | 2 +- test/Transforms/InstSimplify/2011-02-01-Vector.ll | 2 +- .../InstSimplify/2011-09-05-InsertExtractValue.ll | 4 +- test/Transforms/InstSimplify/AndOrXor.ll | 4 +- test/Transforms/InstSimplify/call.ll | 75 +- test/Transforms/InstSimplify/compare.ll | 180 +- test/Transforms/InstSimplify/exact-nsw-nuw.ll | 10 +- test/Transforms/InstSimplify/fast-math.ll | 4 +- test/Transforms/InstSimplify/fdiv.ll | 4 +- .../InstSimplify/floating-point-arithmetic.ll | 8 +- test/Transforms/InstSimplify/lit.local.cfg | 1 - test/Transforms/InstSimplify/maxmin.ll | 56 +- test/Transforms/InstSimplify/phi.ll | 2 +- test/Transforms/InstSimplify/ptr_diff.ll | 10 +- test/Transforms/InstSimplify/reassociate.ll | 42 +- test/Transforms/InstSimplify/rem.ll | 4 +- .../Internalize/2008-05-09-AllButMain.ll | 55 - .../Internalize/2008-05-09-AllButMain.ll.apifile | 2 - test/Transforms/Internalize/apifile | 2 + .../Transforms/Internalize/available_externally.ll | 16 - test/Transforms/Internalize/lists.ll | 50 + test/Transforms/Internalize/lit.local.cfg | 1 - test/Transforms/Internalize/used.ll | 20 + test/Transforms/JumpThreading/basic.ll | 30 +- test/Transforms/JumpThreading/indirectbr.ll | 2 +- test/Transforms/JumpThreading/landing-pad.ll | 203 + test/Transforms/JumpThreading/lit.local.cfg | 1 - test/Transforms/JumpThreading/select.ll | 71 +- test/Transforms/JumpThreading/thread-loads.ll | 8 +- test/Transforms/LCSSA/lit.local.cfg | 1 - .../LICM/2011-04-06-PromoteResultOfPromotion.ll | 6 +- test/Transforms/LICM/atomics.ll | 8 +- test/Transforms/LICM/debug-value.ll | 33 +- test/Transforms/LICM/hoisting.ll | 10 +- test/Transforms/LICM/lit.local.cfg | 1 - test/Transforms/LICM/promote-order.ll | 6 +- test/Transforms/LICM/scalar_promote.ll | 16 +- test/Transforms/LICM/sinking.ll | 22 +- test/Transforms/LICM/speculate.ll | 10 +- test/Transforms/LICM/volatile-alias.ll | 54 + test/Transforms/LoopDeletion/lit.local.cfg | 1 - test/Transforms/LoopIdiom/X86/lit.local.cfg | 2 - test/Transforms/LoopIdiom/basic-address-space.ll | 91 + test/Transforms/LoopIdiom/basic.ll | 32 +- test/Transforms/LoopIdiom/debug-line.ll | 21 +- test/Transforms/LoopIdiom/lit.local.cfg | 1 - test/Transforms/LoopIdiom/memset_noidiom.ll | 2 +- test/Transforms/LoopReroll/basic.ll | 327 + test/Transforms/LoopReroll/reduction.ll | 96 + test/Transforms/LoopRotate/basic.ll | 4 +- test/Transforms/LoopRotate/dbgvalue.ll | 24 +- test/Transforms/LoopRotate/lit.local.cfg | 1 - test/Transforms/LoopRotate/multiple-exits.ll | 4 +- test/Transforms/LoopRotate/phi-duplicate.ll | 2 +- test/Transforms/LoopRotate/simplifylatch.ll | 2 +- test/Transforms/LoopSimplify/dup-preds.ll | 46 + test/Transforms/LoopSimplify/lit.local.cfg | 1 - test/Transforms/LoopSimplify/preserve-scev.ll | 2 +- .../LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll | 4 +- .../LoopStrengthReduce/2011-10-06-ReusePhi.ll | 2 +- .../LoopStrengthReduce/2011-10-13-SCEVChain.ll | 2 +- .../LoopStrengthReduce/2011-10-14-IntPtr.ll | 2 +- .../2011-12-19-PostincQuadratic.ll | 2 +- .../LoopStrengthReduce/2012-01-02-nopreheader.ll | 4 +- .../LoopStrengthReduce/2012-01-16-nopreheader.ll | 2 +- .../LoopStrengthReduce/2012-03-15-nopreheader.ll | 2 +- .../LoopStrengthReduce/2012-07-13-ExpandUDiv.ll | 2 +- .../LoopStrengthReduce/2013-01-05-IndBr.ll | 2 +- .../LoopStrengthReduce/2013-01-14-ReuseCast.ll | 12 +- .../LoopStrengthReduce/ARM/ivchain-ARM.ll | 2 +- .../LoopStrengthReduce/ARM/lit.local.cfg | 2 - .../LoopStrengthReduce/X86/2011-07-20-DoubleIV.ll | 4 +- .../X86/2011-11-29-postincphi.ll | 4 +- .../LoopStrengthReduce/X86/2011-12-04-loserreg.ll | 4 +- .../LoopStrengthReduce/X86/lit.local.cfg | 2 - .../LoopStrengthReduce/addrec-gep-address-space.ll | 88 + .../LoopStrengthReduce/address-space-loop.ll | 56 + .../LoopStrengthReduce/dominate-assert.ll | 43 + test/Transforms/LoopStrengthReduce/ivchain.ll | 2 +- test/Transforms/LoopStrengthReduce/lit.local.cfg | 1 - .../LoopStrengthReduce/lsr-expand-quadratic.ll | 42 + .../LoopStrengthReduce/quadradic-exit-value.ll | 44 +- .../scaling_factor_cost_crash.ll | 68 + .../LoopStrengthReduce/uglygep-address-space.ll | 56 + test/Transforms/LoopStrengthReduce/uglygep.ll | 58 +- test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll | 4 +- test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll | 4 +- test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll | 2 +- test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll | 48 + test/Transforms/LoopUnroll/PowerPC/lit.local.cfg | 4 + test/Transforms/LoopUnroll/basic.ll | 4 +- test/Transforms/LoopUnroll/lit.local.cfg | 1 - test/Transforms/LoopUnroll/pr14167.ll | 2 +- test/Transforms/LoopUnroll/scevunroll.ll | 12 +- test/Transforms/LoopUnroll/unloop.ll | 12 +- test/Transforms/LoopUnswitch/basictest.ll | 2 +- test/Transforms/LoopUnswitch/infinite-loop.ll | 2 +- test/Transforms/LoopUnswitch/lit.local.cfg | 1 - test/Transforms/LoopVectorize/12-12-11-if-conv.ll | 4 +- test/Transforms/LoopVectorize/ARM/arm-unroll.ll | 4 +- test/Transforms/LoopVectorize/ARM/gather-cost.ll | 88 + test/Transforms/LoopVectorize/ARM/gcc-examples.ll | 4 +- test/Transforms/LoopVectorize/ARM/lit.local.cfg | 2 - test/Transforms/LoopVectorize/ARM/width-detect.ll | 18 +- .../LoopVectorize/X86/already-vectorized.ll | 46 + test/Transforms/LoopVectorize/X86/avx1.ll | 4 +- .../LoopVectorize/X86/conversion-cost.ll | 4 +- test/Transforms/LoopVectorize/X86/cost-model.ll | 2 +- test/Transforms/LoopVectorize/X86/gather-cost.ll | 86 + test/Transforms/LoopVectorize/X86/gcc-examples.ll | 8 +- .../X86/illegal-parallel-loop-uniform-write.ll | 6 +- test/Transforms/LoopVectorize/X86/lit.local.cfg | 2 - .../X86/parallel-loops-after-reg2mem.ll | 2 +- .../Transforms/LoopVectorize/X86/parallel-loops.ll | 10 +- test/Transforms/LoopVectorize/X86/rauw-bug.ll | 33 + .../LoopVectorize/X86/reduction-crash.ll | 2 +- test/Transforms/LoopVectorize/X86/small-size.ll | 10 +- test/Transforms/LoopVectorize/X86/tripcount.ll | 39 + test/Transforms/LoopVectorize/X86/unroll-pm.ll | 31 + .../LoopVectorize/X86/unroll-small-loops.ll | 4 +- .../LoopVectorize/X86/x86_fp80-vector-store.ll | 2 +- test/Transforms/LoopVectorize/XCore/lit.local.cfg | 3 + .../LoopVectorize/XCore/no-vector-registers.ll | 23 + test/Transforms/LoopVectorize/align.ll | 33 + test/Transforms/LoopVectorize/bsd_regex.ll | 2 +- test/Transforms/LoopVectorize/cast-induction.ll | 2 +- test/Transforms/LoopVectorize/cpp-new-array.ll | 2 +- test/Transforms/LoopVectorize/dbg.value.ll | 23 +- test/Transforms/LoopVectorize/debugloc.ll | 90 + test/Transforms/LoopVectorize/ee-crash.ll | 35 + test/Transforms/LoopVectorize/flags.ll | 4 +- test/Transforms/LoopVectorize/float-reduction.ll | 2 +- test/Transforms/LoopVectorize/funcall.ll | 32 + test/Transforms/LoopVectorize/gcc-examples.ll | 42 +- test/Transforms/LoopVectorize/global_alias.ll | 49 +- test/Transforms/LoopVectorize/hoist-loads.ll | 69 + test/Transforms/LoopVectorize/if-conv-crash.ll | 22 + .../LoopVectorize/if-conversion-edgemasks.ll | 243 + .../Transforms/LoopVectorize/if-conversion-nest.ll | 2 +- .../LoopVectorize/if-conversion-reduction.ll | 2 +- test/Transforms/LoopVectorize/if-conversion.ll | 67 +- test/Transforms/LoopVectorize/increment.ll | 4 +- test/Transforms/LoopVectorize/induction.ll | 110 + test/Transforms/LoopVectorize/induction_plus.ll | 4 +- test/Transforms/LoopVectorize/infiniteloop.ll | 34 + test/Transforms/LoopVectorize/intrinsic.ll | 229 +- test/Transforms/LoopVectorize/lifetime.ll | 96 + test/Transforms/LoopVectorize/lit.local.cfg | 1 - test/Transforms/LoopVectorize/memdep.ll | 222 + test/Transforms/LoopVectorize/metadata-unroll.ll | 41 + test/Transforms/LoopVectorize/metadata-width.ll | 31 + test/Transforms/LoopVectorize/minmax_reduction.ll | 124 +- .../LoopVectorize/multiple-address-spaces.ll | 44 + test/Transforms/LoopVectorize/no_idiv_reduction.ll | 2 +- test/Transforms/LoopVectorize/no_int_induction.ll | 33 +- test/Transforms/LoopVectorize/no_outside_user.ll | 30 + test/Transforms/LoopVectorize/nofloat.ll | 2 +- test/Transforms/LoopVectorize/non-const-n.ll | 2 +- test/Transforms/LoopVectorize/opt.ll | 28 + test/Transforms/LoopVectorize/ptr_loops.ll | 4 +- test/Transforms/LoopVectorize/read-only.ll | 2 +- test/Transforms/LoopVectorize/reduction.ll | 191 +- test/Transforms/LoopVectorize/reverse_induction.ll | 75 +- test/Transforms/LoopVectorize/reverse_iter.ll | 45 + .../LoopVectorize/runtime-check-address-space.ll | 235 + .../runtime-check-readonly-address-space.ll | 142 + .../LoopVectorize/runtime-check-readonly.ll | 2 +- test/Transforms/LoopVectorize/runtime-check.ll | 30 +- test/Transforms/LoopVectorize/runtime-limit.ll | 4 +- test/Transforms/LoopVectorize/safegep.ll | 61 + test/Transforms/LoopVectorize/same-base-access.ll | 4 +- test/Transforms/LoopVectorize/scalar-select.ll | 2 +- .../Transforms/LoopVectorize/scev-exitlim-crash.ll | 114 + test/Transforms/LoopVectorize/simple-unroll.ll | 2 +- test/Transforms/LoopVectorize/small-loop.ll | 2 +- test/Transforms/LoopVectorize/start-non-zero.ll | 2 +- test/Transforms/LoopVectorize/store-shuffle-bug.ll | 55 + test/Transforms/LoopVectorize/struct_access.ll | 44 +- test/Transforms/LoopVectorize/undef-inst-bug.ll | 36 + test/Transforms/LoopVectorize/unroll_novec.ll | 39 + test/Transforms/LoopVectorize/value-ptr-bug.ll | 2 +- test/Transforms/LoopVectorize/vectorize-once.ll | 19 +- test/Transforms/LoopVectorize/write-only.ll | 2 +- test/Transforms/LowerAtomic/atomic-load.ll | 6 +- test/Transforms/LowerAtomic/atomic-swap.ll | 4 +- test/Transforms/LowerAtomic/barrier.ll | 2 +- test/Transforms/LowerAtomic/lit.local.cfg | 1 - test/Transforms/LowerExpectIntrinsic/basic.ll | 16 +- test/Transforms/LowerExpectIntrinsic/lit.local.cfg | 1 - test/Transforms/LowerInvoke/lit.local.cfg | 1 - test/Transforms/LowerSwitch/feature.ll | 64 +- test/Transforms/LowerSwitch/lit.local.cfg | 1 - test/Transforms/Mem2Reg/ConvertDebugInfo.ll | 15 +- test/Transforms/Mem2Reg/ConvertDebugInfo2.ll | 20 +- test/Transforms/Mem2Reg/atomic.ll | 2 +- test/Transforms/Mem2Reg/lit.local.cfg | 1 - test/Transforms/MemCpyOpt/align.ll | 4 +- test/Transforms/MemCpyOpt/form-memset.ll | 18 +- test/Transforms/MemCpyOpt/lit.local.cfg | 1 - test/Transforms/MemCpyOpt/loadstore-sret.ll | 2 +- test/Transforms/MemCpyOpt/memcpy-to-memset.ll | 2 +- test/Transforms/MemCpyOpt/memcpy.ll | 31 +- test/Transforms/MemCpyOpt/memmove.ll | 6 +- test/Transforms/MergeFunc/address-spaces.ll | 35 + .../Transforms/MergeFunc/inttoptr-address-space.ll | 29 + test/Transforms/MergeFunc/inttoptr.ll | 1 + test/Transforms/MergeFunc/lit.local.cfg | 1 - test/Transforms/MergeFunc/merge-ptr-and-int.ll | 27 + .../Transforms/MergeFunc/ptr-int-transitivity-1.ll | 21 + .../Transforms/MergeFunc/ptr-int-transitivity-2.ll | 25 + .../Transforms/MergeFunc/ptr-int-transitivity-3.ll | 21 + test/Transforms/MergeFunc/too-small.ll | 14 + test/Transforms/MetaRenamer/lit.local.cfg | 1 - test/Transforms/ObjCARC/allocas.ll | 500 + test/Transforms/ObjCARC/arc-annotations.ll | 2 +- test/Transforms/ObjCARC/basic.ll | 294 +- test/Transforms/ObjCARC/cfg-hazards.ll | 6 +- test/Transforms/ObjCARC/contract-storestrong.ll | 6 +- test/Transforms/ObjCARC/contract-testcases.ll | 4 +- test/Transforms/ObjCARC/contract.ll | 26 +- test/Transforms/ObjCARC/empty-block.ll | 4 +- ...ensure-that-exception-unwind-path-is-visited.ll | 58 +- test/Transforms/ObjCARC/escape.ll | 4 +- test/Transforms/ObjCARC/gvn.ll | 25 +- test/Transforms/ObjCARC/intrinsic-use-isolated.ll | 2 +- test/Transforms/ObjCARC/intrinsic-use.ll | 4 +- test/Transforms/ObjCARC/invoke.ll | 12 +- test/Transforms/ObjCARC/lit.local.cfg | 1 - test/Transforms/ObjCARC/nested.ll | 24 +- test/Transforms/ObjCARC/no-objc-arc-exceptions.ll | 123 - test/Transforms/ObjCARC/path-overflow.ll | 1876 +- test/Transforms/ObjCARC/pointer-types.ll | 2 +- test/Transforms/ObjCARC/post-inlining.ll | 6 +- test/Transforms/ObjCARC/retain-block-alloca.ll | 94 - .../ObjCARC/retain-block-escape-analysis.ll | 215 - test/Transforms/ObjCARC/retain-block-load.ll | 51 - test/Transforms/ObjCARC/retain-block.ll | 140 - test/Transforms/ObjCARC/retain-not-declared.ll | 2 +- test/Transforms/ObjCARC/rv.ll | 22 +- test/Transforms/ObjCARC/split-backedge.ll | 2 +- test/Transforms/ObjCARC/weak.ll | 2 +- test/Transforms/PhaseOrdering/PR6627.ll | 4 +- test/Transforms/PhaseOrdering/basic.ll | 4 +- test/Transforms/PhaseOrdering/lit.local.cfg | 1 - test/Transforms/PruneEH/lit.local.cfg | 1 - .../Transforms/Reassociate/2012-05-08-UndefLeak.ll | 2 +- test/Transforms/Reassociate/absorption.ll | 2 +- test/Transforms/Reassociate/basictest.ll | 30 +- test/Transforms/Reassociate/inverses.ll | 6 +- test/Transforms/Reassociate/lit.local.cfg | 1 - test/Transforms/Reassociate/mulfactor.ll | 14 +- test/Transforms/Reassociate/multistep.ll | 4 +- test/Transforms/Reassociate/no-op.ll | 4 +- test/Transforms/Reassociate/optional-flags.ll | 4 +- test/Transforms/Reassociate/repeats.ll | 32 +- test/Transforms/Reassociate/xor_reassoc.ll | 22 +- test/Transforms/Reg2Mem/lit.local.cfg | 1 - test/Transforms/SCCP/atomic-load-store.ll | 4 +- test/Transforms/SCCP/ipsccp-addr-taken.ll | 2 +- test/Transforms/SCCP/ipsccp-basic.ll | 28 +- test/Transforms/SCCP/lit.local.cfg | 1 - test/Transforms/SCCP/sccptest.ll | 4 +- test/Transforms/SCCP/switch.ll | 2 +- test/Transforms/SCCP/undef-resolve.ll | 20 +- test/Transforms/SLPVectorizer/ARM/lit.local.cfg | 3 + test/Transforms/SLPVectorizer/ARM/memory.ll | 20 + test/Transforms/SLPVectorizer/ARM/sroa.ll | 52 + test/Transforms/SLPVectorizer/R600/lit.local.cfg | 4 + test/Transforms/SLPVectorizer/R600/simplebb.ll | 65 + test/Transforms/SLPVectorizer/X86/barriercall.ll | 2 +- test/Transforms/SLPVectorizer/X86/cast.ll | 2 +- test/Transforms/SLPVectorizer/X86/cmp_sel.ll | 32 + .../Transforms/SLPVectorizer/X86/compare-reduce.ll | 2 +- test/Transforms/SLPVectorizer/X86/crash_7zip.ll | 38 + test/Transforms/SLPVectorizer/X86/crash_bullet.ll | 128 + test/Transforms/SLPVectorizer/X86/crash_bullet3.ll | 84 + test/Transforms/SLPVectorizer/X86/crash_dequeue.ll | 40 + test/Transforms/SLPVectorizer/X86/crash_flop7.ll | 46 + test/Transforms/SLPVectorizer/X86/crash_lencod.ll | 91 + .../SLPVectorizer/X86/crash_mandeltext.ll | 107 + .../SLPVectorizer/X86/crash_netbsd_decompress.ll | 41 + test/Transforms/SLPVectorizer/X86/crash_sim4b1.ll | 113 + test/Transforms/SLPVectorizer/X86/crash_smallpt.ll | 105 + .../SLPVectorizer/X86/cross_block_slp.ll | 54 + test/Transforms/SLPVectorizer/X86/cse.ll | 219 + test/Transforms/SLPVectorizer/X86/cycle_dup.ll | 64 + test/Transforms/SLPVectorizer/X86/debug_info.ll | 89 + test/Transforms/SLPVectorizer/X86/diamond.ll | 47 +- test/Transforms/SLPVectorizer/X86/external_user.ll | 96 + test/Transforms/SLPVectorizer/X86/extract.ll | 59 + test/Transforms/SLPVectorizer/X86/horizontal.ll | 417 + test/Transforms/SLPVectorizer/X86/implicitfloat.ll | 25 + test/Transforms/SLPVectorizer/X86/in-tree-user.ll | 50 + .../X86/insert-element-build-vector.ll | 197 + test/Transforms/SLPVectorizer/X86/lit.local.cfg | 2 - test/Transforms/SLPVectorizer/X86/long_chains.ll | 47 + test/Transforms/SLPVectorizer/X86/loopinvariant.ll | 2 +- test/Transforms/SLPVectorizer/X86/multi_block.ll | 55 + test/Transforms/SLPVectorizer/X86/multi_user.ll | 2 +- test/Transforms/SLPVectorizer/X86/odd_store.ll | 46 + test/Transforms/SLPVectorizer/X86/operandorder.ll | 234 + test/Transforms/SLPVectorizer/X86/opt.ll | 30 + test/Transforms/SLPVectorizer/X86/ordering.ll | 81 + test/Transforms/SLPVectorizer/X86/phi.ll | 248 + test/Transforms/SLPVectorizer/X86/phi3.ll | 35 + .../Transforms/SLPVectorizer/X86/phi_landingpad.ll | 31 + .../SLPVectorizer/X86/phi_overalignedtype.ll | 45 + test/Transforms/SLPVectorizer/X86/pr16571.ll | 22 + test/Transforms/SLPVectorizer/X86/pr16628.ll | 27 + test/Transforms/SLPVectorizer/X86/pr16899.ll | 31 + test/Transforms/SLPVectorizer/X86/pr18060.ll | 47 + test/Transforms/SLPVectorizer/X86/reduction2.ll | 6 +- test/Transforms/SLPVectorizer/X86/rgb_phi.ll | 76 + test/Transforms/SLPVectorizer/X86/saxpy.ll | 16 + test/Transforms/SLPVectorizer/X86/simplebb.ll | 64 + test/Transforms/SLPVectorizer/X86/tiny-tree.ll | 140 + test/Transforms/SLPVectorizer/XCore/lit.local.cfg | 3 + .../SLPVectorizer/XCore/no-vector-registers.ll | 24 + test/Transforms/SLPVectorizer/lit.local.cfg | 1 - test/Transforms/SROA/alignment.ll | 14 +- test/Transforms/SROA/basictest.ll | 107 +- test/Transforms/SROA/big-endian.ll | 4 +- test/Transforms/SROA/fca.ll | 4 +- test/Transforms/SROA/lit.local.cfg | 1 - test/Transforms/SROA/phi-and-select.ll | 106 +- test/Transforms/SROA/vector-conversion.ll | 53 + test/Transforms/SROA/vector-promotion.ll | 22 +- test/Transforms/SampleProfile/Inputs/branch.prof | 11 + test/Transforms/SampleProfile/branch.ll | 143 + .../Transforms/ScalarRepl/2008-09-22-vector-gep.ll | 2 +- test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll | 4 +- test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll | 2 +- .../ScalarRepl/2011-09-22-PHISpeculateInvoke.ll | 2 +- .../ScalarRepl/2011-10-22-VectorCrash.ll | 2 +- test/Transforms/ScalarRepl/address-space.ll | 2 +- test/Transforms/ScalarRepl/badarray.ll | 6 +- test/Transforms/ScalarRepl/basictest.ll | 4 +- test/Transforms/ScalarRepl/debuginfo-preserved.ll | 13 +- test/Transforms/ScalarRepl/inline-vector.ll | 2 +- test/Transforms/ScalarRepl/lifetime.ll | 12 +- test/Transforms/ScalarRepl/lit.local.cfg | 1 - test/Transforms/ScalarRepl/memset-aggregate.ll | 2 +- test/Transforms/ScalarRepl/nonzero-first-index.ll | 8 +- test/Transforms/ScalarRepl/only-memcpy-uses.ll | 2 +- test/Transforms/ScalarRepl/phi-select.ll | 16 +- test/Transforms/ScalarRepl/union-pointer.ll | 43 +- test/Transforms/ScalarRepl/vector_promote.ll | 38 +- ...2009-01-19-UnconditionalTrappingConstantExpr.ll | 4 +- test/Transforms/SimplifyCFG/CoveredLookupTable.ll | 48 + .../SimplifyCFG/EqualPHIEdgeBlockMerge.ll | 240 +- test/Transforms/SimplifyCFG/MagicPointer.ll | 94 +- test/Transforms/SimplifyCFG/PR16069.ll | 28 + test/Transforms/SimplifyCFG/SPARC/lit.local.cfg | 2 - .../SimplifyCFG/SPARC/switch_to_lookup_table.ll | 2 +- test/Transforms/SimplifyCFG/SpeculativeExec.ll | 6 +- .../Transforms/SimplifyCFG/UnreachableEliminate.ll | 6 +- test/Transforms/SimplifyCFG/X86/lit.local.cfg | 2 - .../SimplifyCFG/X86/switch_to_lookup_table.ll | 29 +- test/Transforms/SimplifyCFG/attr-noduplicate.ll | 37 + test/Transforms/SimplifyCFG/basictest.ll | 8 +- test/Transforms/SimplifyCFG/branch-fold-dbg.ll | 17 +- test/Transforms/SimplifyCFG/common-dest-folding.ll | 57 + .../dce-cond-after-folding-terminator.ll | 6 +- test/Transforms/SimplifyCFG/hoist-dbgvalue.ll | 19 +- test/Transforms/SimplifyCFG/indirectbr.ll | 8 +- test/Transforms/SimplifyCFG/invoke.ll | 12 +- test/Transforms/SimplifyCFG/invoke_unwind.ll | 2 +- test/Transforms/SimplifyCFG/lit.local.cfg | 1 - test/Transforms/SimplifyCFG/phi-undef-loadstore.ll | 8 +- .../SimplifyCFG/preserve-branchweights-partial.ll | 2 +- .../SimplifyCFG/preserve-branchweights.ll | 16 +- test/Transforms/SimplifyCFG/select-gep.ll | 4 +- test/Transforms/SimplifyCFG/speculate-store.ll | 8 +- .../SimplifyCFG/speculate-with-offset.ll | 8 +- test/Transforms/SimplifyCFG/switch-masked-bits.ll | 4 +- .../SimplifyCFG/switch-on-const-select.ll | 10 +- test/Transforms/SimplifyCFG/switch-to-icmp.ll | 6 +- test/Transforms/SimplifyCFG/switch_create.ll | 121 +- test/Transforms/SimplifyCFG/trap-debugloc.ll | 15 +- .../SimplifyCFG/trapping-load-unreachable.ll | 12 +- test/Transforms/SimplifyCFG/volatile-phioper.ll | 6 +- .../SimplifyLibCalls/2005-05-20-sprintf-crash.ll | 11 - .../2007-04-06-strchr-miscompile.ll | 29 - .../SimplifyLibCalls/2008-05-19-memcmp.ll | 14 - .../SimplifyLibCalls/2009-05-30-memcmp-byte.ll | 14 - .../Transforms/SimplifyLibCalls/2009-07-28-Exit.ll | 22 - .../SimplifyLibCalls/2009-07-29-Exit2.ll | 24 - test/Transforms/SimplifyLibCalls/MemCpy.ll | 19 - test/Transforms/SimplifyLibCalls/PR7357.ll | 16 - .../SimplifyLibCalls/float-shrink-compare.ll | 179 - test/Transforms/SimplifyLibCalls/lit.local.cfg | 1 - test/Transforms/SimplifyLibCalls/win-math.ll | 275 - test/Transforms/Sink/basic.ll | 6 +- test/Transforms/Sink/lit.local.cfg | 1 - .../StripSymbols/2007-01-15-llvm.used.ll | 9 +- .../StripSymbols/2010-06-30-StripDebug.ll | 20 +- .../StripSymbols/2010-07-01-DeadDbgInfo.ll | 47 - test/Transforms/StripSymbols/2010-08-25-crash.ll | 25 +- test/Transforms/StripSymbols/lit.local.cfg | 1 - .../StripSymbols/strip-dead-debug-info.ll | 58 + .../StructurizeCFG/branch-on-argument.ll | 47 + .../StructurizeCFG/loop-multiple-exits.ll | 50 + .../StructurizeCFG/no-branch-to-entry.ll | 31 + test/Transforms/StructurizeCFG/switch.ll | 23 + .../2010-06-26-MultipleReturnValues.ll | 2 +- test/Transforms/TailCallElim/accum_recursion.ll | 6 +- test/Transforms/TailCallElim/basic.ll | 145 + .../TailCallElim/dont-tce-tail-marked-call.ll | 13 - test/Transforms/TailCallElim/inf-recursion.ll | 4 +- test/Transforms/TailCallElim/intervening-inst.ll | 18 - test/Transforms/TailCallElim/lit.local.cfg | 1 - .../TailCallElim/move_alloca_for_tail_call.ll | 15 - test/Transforms/TailCallElim/nocapture.ll | 25 - test/Transforms/TailCallElim/return_constant.ll | 18 - .../TailCallElim/trivial_codegen_tailcall.ll | 11 - test/Transforms/TailDup/X86/lit.local.cfg | 2 - test/Transforms/TailDup/lit.local.cfg | 2 - test/Unit/lit.cfg | 16 +- test/Unit/lit.site.cfg.in | 13 +- .../bitcast-address-space-nested-global-cycle.ll | 8 + .../bitcast-address-space-nested-global.ll | 11 + ...ugh-constant-inttoptr-inside-gep-instruction.ll | 10 + ...cast-address-space-through-constant-inttoptr.ll | 11 + .../bitcast-address-space-through-gep-2.ll | 17 + test/Verifier/bitcast-address-space-through-gep.ll | 13 + .../bitcast-address-space-through-inttoptr.ll | 9 + test/Verifier/bitcast-address-spaces.ll | 9 + test/Verifier/bitcast-alias-address-space.ll | 8 + test/Verifier/bitcast-vector-pointer-as.ll | 9 + test/Verifier/ident-meta1.ll | 12 + test/Verifier/ident-meta2.ll | 13 + test/Verifier/ident-meta3.ll | 10 + test/Verifier/lit.local.cfg | 1 - test/Verifier/llvm.compiler_used-invalid-type.ll | 4 +- test/Verifier/llvm.used-invalid-type2.ll | 2 +- test/Verifier/varargs-intrinsic.ll | 16 + test/YAMLParser/spec-02-24.data | 7 +- test/YAMLParser/spec-07-04.data | 4 +- test/YAMLParser/yaml.data | 8 +- test/lit.cfg | 158 +- test/lit.site.cfg.in | 12 +- test/tools/llvm-cov/Inputs/README | 7 + test/tools/llvm-cov/Inputs/test.cpp | 77 + test/tools/llvm-cov/Inputs/test.cpp.gcov | 82 + test/tools/llvm-cov/Inputs/test.gcda | Bin 0 -> 824 bytes test/tools/llvm-cov/Inputs/test.gcno | Bin 0 -> 3112 bytes test/tools/llvm-cov/Inputs/test_read_fail.gcno | Bin 0 -> 111 bytes test/tools/llvm-cov/lit.local.cfg | 1 + test/tools/llvm-cov/llvm-cov.test | 10 + test/tools/llvm-lit/lit.local.cfg | 1 - test/tools/llvm-objdump/Inputs/nop.exe.coff-i386 | Bin 0 -> 7680 bytes .../tools/llvm-objdump/Inputs/trivial.obj.elf-i386 | Bin 0 -> 449 bytes .../Inputs/win64-unwind.exe.coff-x86_64 | Bin 0 -> 698 bytes .../Inputs/win64-unwind.exe.coff-x86_64.asm | 53 + test/tools/llvm-objdump/coff-private-headers.test | 9 + test/tools/llvm-objdump/disassembly-show-raw.s | 15 - test/tools/llvm-objdump/disassembly-show-raw.test | 14 + test/tools/llvm-objdump/lit.local.cfg | 3 - test/tools/llvm-objdump/win64-unwind-data.s | 106 - test/tools/llvm-objdump/win64-unwind-data.test | 52 + test/tools/llvm-readobj/Inputs/dynamic-table.c | 7 + test/tools/llvm-readobj/Inputs/dynamic-table.mips | Bin 0 -> 5395 bytes .../tools/llvm-readobj/Inputs/magic.coff-importlib | Bin 0 -> 40 bytes test/tools/llvm-readobj/Inputs/magic.coff-unknown | Bin 0 -> 450 bytes test/tools/llvm-readobj/Inputs/relocs.py | 25 - .../tools/llvm-readobj/Inputs/rpath.exe.elf-x86_64 | Bin 0 -> 5632 bytes .../llvm-readobj/Inputs/trivial.exe.coff-i386 | Bin 0 -> 2560 bytes test/tools/llvm-readobj/dynamic.test | 33 + test/tools/llvm-readobj/file-headers.test | 118 + test/tools/llvm-readobj/lit.local.cfg | 1 - test/tools/llvm-readobj/program-headers.test | 30 + test/tools/llvm-readobj/reloc-types.test | 23 - test/tools/llvm-readobj/relocations.test | 2 +- test/tools/llvm-readobj/rpath.test | 4 + test/tools/llvm-readobj/sections-ext.test | 30 +- test/tools/llvm-readobj/symbols.test | 9 + tools/CMakeLists.txt | 93 +- tools/LLVMBuild.txt | 2 +- tools/Makefile | 21 +- tools/bugpoint/BugDriver.cpp | 4 +- tools/bugpoint/BugDriver.h | 4 +- tools/bugpoint/CrashDebugger.cpp | 20 +- tools/bugpoint/ExecutionDriver.cpp | 63 +- tools/bugpoint/ExtractFunction.cpp | 30 +- tools/bugpoint/FindBugs.cpp | 3 +- tools/bugpoint/Miscompilation.cpp | 101 +- tools/bugpoint/OptimizerDriver.cpp | 99 +- tools/bugpoint/ToolRunner.cpp | 201 +- tools/bugpoint/ToolRunner.h | 60 +- tools/bugpoint/bugpoint.cpp | 6 +- tools/gold/README.txt | 20 +- tools/gold/gold-plugin.cpp | 66 +- tools/llc/llc.cpp | 9 +- tools/lli/CMakeLists.txt | 7 +- tools/lli/ChildTarget/CMakeLists.txt | 3 + tools/lli/ChildTarget/ChildTarget.cpp | 242 + tools/lli/ChildTarget/LLVMBuild.txt | 21 + tools/lli/ChildTarget/Makefile | 17 + tools/lli/ChildTarget/Unix/ChildTarget.inc | 166 + tools/lli/ChildTarget/Windows/ChildTarget.inc | 44 + tools/lli/LLVMBuild.txt | 5 +- tools/lli/Makefile | 4 +- tools/lli/RecordingMemoryManager.cpp | 128 - tools/lli/RecordingMemoryManager.h | 87 - tools/lli/RemoteMemoryManager.cpp | 206 + tools/lli/RemoteMemoryManager.h | 114 + tools/lli/RemoteTarget.cpp | 31 + tools/lli/RemoteTarget.h | 27 +- tools/lli/RemoteTargetExternal.cpp | 162 + tools/lli/RemoteTargetExternal.h | 118 + tools/lli/RemoteTargetMessage.h | 45 + tools/lli/Unix/RemoteTargetExternal.inc | 96 + tools/lli/Windows/RemoteTargetExternal.inc | 35 + tools/lli/lli.cpp | 322 +- tools/llvm-ar/CMakeLists.txt | 20 +- tools/llvm-ar/LLVMBuild.txt | 1 - tools/llvm-ar/Makefile | 3 +- tools/llvm-ar/llvm-ar.cpp | 1146 +- tools/llvm-as/llvm-as.cpp | 5 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 3 +- tools/llvm-c-test/CMakeLists.txt | 16 + tools/llvm-c-test/Makefile | 29 + tools/llvm-c-test/calc.c | 148 + tools/llvm-c-test/disassemble.c | 88 + tools/llvm-c-test/helpers.c | 40 + tools/llvm-c-test/include-all.c | 33 + tools/llvm-c-test/llvm-c-test.h | 37 + tools/llvm-c-test/main.c | 73 + tools/llvm-c-test/module.c | 116 + tools/llvm-c-test/object.c | 88 + tools/llvm-c-test/targets.c | 30 + tools/llvm-config/CMakeLists.txt | 35 +- tools/llvm-config/llvm-config.cpp | 6 +- tools/llvm-cov/CMakeLists.txt | 2 +- tools/llvm-cov/Makefile | 2 +- tools/llvm-cov/llvm-cov.cpp | 16 +- tools/llvm-diff/DifferenceEngine.cpp | 10 +- tools/llvm-diff/llvm-diff.cpp | 2 +- tools/llvm-dis/llvm-dis.cpp | 5 +- tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 5 + tools/llvm-extract/llvm-extract.cpp | 5 +- tools/llvm-link/llvm-link.cpp | 18 +- tools/llvm-lto/CMakeLists.txt | 6 + tools/llvm-lto/LLVMBuild.txt | 22 + tools/llvm-lto/Makefile | 19 + tools/llvm-lto/llvm-lto.cpp | 187 + tools/llvm-mc/Disassembler.cpp | 72 +- tools/llvm-mc/llvm-mc.cpp | 22 +- tools/llvm-nm/CMakeLists.txt | 2 +- tools/llvm-nm/LLVMBuild.txt | 2 +- tools/llvm-nm/Makefile | 2 +- tools/llvm-nm/llvm-nm.cpp | 279 +- tools/llvm-objdump/CMakeLists.txt | 1 - tools/llvm-objdump/COFFDump.cpp | 50 +- tools/llvm-objdump/ELFDump.cpp | 30 +- tools/llvm-objdump/MCFunction.cpp | 138 - tools/llvm-objdump/MCFunction.h | 100 - tools/llvm-objdump/MachODump.cpp | 456 +- tools/llvm-objdump/llvm-objdump.cpp | 246 +- tools/llvm-objdump/llvm-objdump.h | 22 +- tools/llvm-prof/CMakeLists.txt | 5 - tools/llvm-prof/LLVMBuild.txt | 22 - tools/llvm-prof/Makefile | 17 - tools/llvm-prof/llvm-prof.cpp | 293 - tools/llvm-ranlib/CMakeLists.txt | 5 - tools/llvm-ranlib/LLVMBuild.txt | 22 - tools/llvm-ranlib/Makefile | 17 - tools/llvm-ranlib/llvm-ranlib.cpp | 98 - tools/llvm-readobj/CMakeLists.txt | 1 - tools/llvm-readobj/COFFDumper.cpp | 126 +- tools/llvm-readobj/ELFDumper.cpp | 427 +- tools/llvm-readobj/LLVMBuild.txt | 2 +- tools/llvm-readobj/MachODumper.cpp | 75 +- tools/llvm-readobj/Makefile | 2 +- tools/llvm-readobj/llvm-readobj.cpp | 7 +- tools/llvm-rtdyld/llvm-rtdyld.cpp | 30 +- tools/llvm-shlib/Makefile | 11 +- tools/llvm-stress/llvm-stress.cpp | 9 +- tools/llvm-symbolizer/LLVMSymbolize.cpp | 254 +- tools/llvm-symbolizer/LLVMSymbolize.h | 40 +- tools/llvm-symbolizer/llvm-symbolizer.cpp | 6 +- tools/lto/CMakeLists.txt | 33 +- tools/lto/LTOCodeGenerator.cpp | 432 - tools/lto/LTOCodeGenerator.h | 83 - tools/lto/LTOModule.cpp | 918 - tools/lto/LTOModule.h | 191 - tools/lto/Makefile | 5 +- tools/lto/lto.cpp | 120 +- tools/macho-dump/macho-dump.cpp | 245 +- tools/msbuild/CMakeLists.txt | 42 + .../Microsoft.Cpp.Win32.LLVM-vs2010.targets | 2 + .../Microsoft.Cpp.Win32.LLVM-vs2012.targets | 3 + .../Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets | 21 + tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in | 18 + tools/msbuild/install.bat | 81 + tools/msbuild/toolset-vs2013.targets | 3 + tools/msbuild/toolset-vs2013_xp.targets | 21 + tools/msbuild/uninstall.bat | 50 + tools/obj2yaml/CMakeLists.txt | 2 +- tools/obj2yaml/coff2yaml.cpp | 377 +- tools/obj2yaml/obj2yaml.cpp | 32 - tools/obj2yaml/obj2yaml.h | 12 - tools/opt/opt.cpp | 55 +- tools/yaml2obj/CMakeLists.txt | 4 + tools/yaml2obj/Makefile | 2 +- tools/yaml2obj/yaml2coff.cpp | 288 + tools/yaml2obj/yaml2elf.cpp | 401 + tools/yaml2obj/yaml2obj.cpp | 661 +- tools/yaml2obj/yaml2obj.h | 22 + unittests/ADT/APFloatTest.cpp | 1824 +- unittests/ADT/APIntTest.cpp | 65 + unittests/ADT/BitVectorTest.cpp | 60 + unittests/ADT/CMakeLists.txt | 2 + unittests/ADT/IntrusiveRefCntPtrTest.cpp | 8 +- unittests/ADT/PointerUnionTest.cpp | 64 + unittests/ADT/StringRefTest.cpp | 52 + unittests/ADT/polymorphic_ptr_test.cpp | 129 + unittests/Analysis/CFGTest.cpp | 376 + unittests/Analysis/CMakeLists.txt | 2 + unittests/Analysis/Makefile | 2 +- unittests/CMakeLists.txt | 9 +- unittests/CodeGen/CMakeLists.txt | 13 + unittests/CodeGen/DIEHashTest.cpp | 517 + unittests/CodeGen/Makefile | 16 + unittests/DebugInfo/DWARFFormValueTest.cpp | 22 +- .../ExecutionEngine/JIT/JITMemoryManagerTest.cpp | 23 + unittests/ExecutionEngine/JIT/JITTest.cpp | 173 +- unittests/ExecutionEngine/MCJIT/CMakeLists.txt | 2 +- unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 175 +- .../MCJIT/MCJITMemoryManagerTest.cpp | 344 +- .../MCJIT/MCJITMultipleModuleTest.cpp | 395 + .../ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp | 24 +- unittests/ExecutionEngine/MCJIT/MCJITTest.cpp | 113 +- .../ExecutionEngine/MCJIT/MCJITTestAPICommon.h | 20 +- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h | 217 +- unittests/ExecutionEngine/MCJIT/Makefile | 2 +- unittests/IR/AttributesTest.cpp | 13 + unittests/IR/CMakeLists.txt | 1 + unittests/IR/IRBuilderTest.cpp | 55 +- unittests/IR/InstructionsTest.cpp | 146 +- unittests/IR/LegacyPassManagerTest.cpp | 559 + unittests/IR/PassManagerTest.cpp | 625 +- unittests/IR/ValueTest.cpp | 40 + unittests/IR/VerifierTest.cpp | 23 +- unittests/IR/WaymarkTest.cpp | 1 + unittests/MC/CMakeLists.txt | 11 + unittests/MC/MCAtomTest.cpp | 31 + unittests/MC/Makefile | 15 + unittests/Makefile | 4 +- unittests/Object/CMakeLists.txt | 7 + unittests/Object/Makefile | 15 + unittests/Object/YAMLTest.cpp | 38 + unittests/Option/Makefile | 23 + unittests/Option/OptionParsingTest.cpp | 123 +- unittests/Option/Opts.td | 23 +- unittests/Support/BlockFrequencyTest.cpp | 156 + unittests/Support/CMakeLists.txt | 9 +- unittests/Support/Casting.cpp | 25 + unittests/Support/CommandLineTest.cpp | 43 + unittests/Support/CompressionTest.cpp | 6 + unittests/Support/ConstantRangeTest.cpp | 3 + unittests/Support/ConvertUTFTest.cpp | 65 + unittests/Support/ErrorOrTest.cpp | 38 - unittests/Support/FileOutputBufferTest.cpp | 8 +- unittests/Support/IntegersSubsetTest.cpp | 326 - unittests/Support/LockFileManagerTest.cpp | 48 + unittests/Support/MD5Test.cpp | 60 + unittests/Support/Makefile | 2 +- unittests/Support/ManagedStatic.cpp | 3 +- unittests/Support/MathExtrasTest.cpp | 119 +- unittests/Support/MemoryBufferTest.cpp | 77 +- unittests/Support/Path.cpp | 259 +- unittests/Support/ProcessTest.cpp | 30 +- unittests/Support/ProgramTest.cpp | 121 +- unittests/Support/RegexTest.cpp | 23 + unittests/Support/SourceMgrTest.cpp | 174 + unittests/Support/ThreadLocalTest.cpp | 38 + unittests/Support/TimeValue.cpp | 23 - unittests/Support/TimeValueTest.cpp | 39 + unittests/Support/UnicodeTest.cpp | 93 + unittests/Support/YAMLIOTest.cpp | 441 +- unittests/Transforms/CMakeLists.txt | 1 + unittests/Transforms/DebugIR/CMakeLists.txt | 7 + unittests/Transforms/DebugIR/DebugIR.cpp | 307 + unittests/Transforms/DebugIR/Makefile | 15 + unittests/Transforms/Makefile | 2 +- unittests/Transforms/Utils/CMakeLists.txt | 1 + unittests/Transforms/Utils/SpecialCaseList.cpp | 232 + utils/FileCheck/CMakeLists.txt | 2 +- utils/FileCheck/FileCheck.cpp | 691 +- utils/FileUpdate/CMakeLists.txt | 2 +- utils/FileUpdate/FileUpdate.cpp | 4 +- utils/GetRepositoryPath | 4 +- utils/Misc/mergefunctions.clang.svn.patch | 14 + utils/TableGen/AsmMatcherEmitter.cpp | 278 +- utils/TableGen/AsmWriterEmitter.cpp | 138 +- utils/TableGen/AsmWriterInst.cpp | 55 +- utils/TableGen/CodeGenDAGPatterns.cpp | 160 +- utils/TableGen/CodeGenDAGPatterns.h | 6 +- utils/TableGen/CodeGenInstruction.cpp | 17 +- utils/TableGen/CodeGenInstruction.h | 3 + utils/TableGen/CodeGenIntrinsics.h | 4 +- utils/TableGen/CodeGenMapTable.cpp | 1 - utils/TableGen/CodeGenRegisters.cpp | 244 +- utils/TableGen/CodeGenRegisters.h | 43 +- utils/TableGen/CodeGenSchedule.cpp | 63 +- utils/TableGen/CodeGenSchedule.h | 5 +- utils/TableGen/CodeGenTarget.cpp | 15 +- utils/TableGen/DAGISelEmitter.cpp | 16 +- utils/TableGen/DAGISelMatcher.cpp | 6 +- utils/TableGen/DAGISelMatcher.h | 32 +- utils/TableGen/DAGISelMatcherEmitter.cpp | 15 +- utils/TableGen/DAGISelMatcherOpt.cpp | 6 +- utils/TableGen/FastISelEmitter.cpp | 92 +- utils/TableGen/FixedLenDecoderEmitter.cpp | 22 +- utils/TableGen/InstrInfoEmitter.cpp | 205 +- utils/TableGen/IntrinsicEmitter.cpp | 178 +- utils/TableGen/OptParserEmitter.cpp | 40 +- utils/TableGen/RegisterInfoEmitter.cpp | 83 +- utils/TableGen/SequenceToOffsetTable.h | 1 + utils/TableGen/SetTheory.cpp | 49 +- utils/TableGen/StringToOffsetTable.h | 83 - utils/TableGen/SubtargetEmitter.cpp | 20 +- utils/TableGen/TGValueTypes.cpp | 11 +- utils/TableGen/X86DisassemblerTables.cpp | 244 +- utils/TableGen/X86DisassemblerTables.h | 60 +- utils/TableGen/X86RecognizableInstr.cpp | 306 +- utils/TableGen/X86RecognizableInstr.h | 12 + utils/buildit/build_llvm | 4 +- utils/emacs/llvm-mode.el | 15 +- utils/fpcmp/fpcmp.cpp | 5 +- utils/kate/llvm.xml | 3 +- utils/lit/TODO | 168 +- utils/lit/examples/README.txt | 7 + utils/lit/examples/many-tests/README.txt | 10 + utils/lit/examples/many-tests/lit.cfg | 23 + utils/lit/lit/ExampleTests/Clang/fsyntax-only.c | 4 - utils/lit/lit/ExampleTests/Clang/lit.cfg | 47 - .../lit/ExampleTests/LLVM.InTree/test/Bar/data.txt | 1 - .../lit/ExampleTests/LLVM.InTree/test/Bar/pct-S.ll | 1 - .../lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg | 66 - .../lit/ExampleTests/LLVM.InTree/test/lit.site.cfg | 7 - .../lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg | 1 - .../LLVM.OutOfTree/obj/test/Foo/lit.local.cfg | 0 .../LLVM.OutOfTree/obj/test/lit.site.cfg | 8 - .../LLVM.OutOfTree/src/test/Foo/data.txt | 1 - .../LLVM.OutOfTree/src/test/Foo/pct-S.ll | 1 - .../ExampleTests/LLVM.OutOfTree/src/test/lit.cfg | 66 - utils/lit/lit/ExampleTests/ManyTests/lit.local.cfg | 23 - .../lit/lit/ExampleTests/ShExternal/lit.local.cfg | 6 - .../lit/lit/ExampleTests/ShInternal/lit.local.cfg | 6 - utils/lit/lit/ExampleTests/fail.c | 2 - utils/lit/lit/ExampleTests/lit.cfg | 26 - utils/lit/lit/ExampleTests/pass.c | 1 - utils/lit/lit/ExampleTests/required-and-missing.c | 4 - utils/lit/lit/ExampleTests/required-and-present.c | 2 - utils/lit/lit/ExampleTests/vg-fail.c | 4 - utils/lit/lit/ExampleTests/xfail-feature.c | 4 - utils/lit/lit/ExampleTests/xfail.c | 2 - utils/lit/lit/ExampleTests/xpass.c | 2 - utils/lit/lit/LitConfig.py | 54 +- utils/lit/lit/LitTestCase.py | 22 +- utils/lit/lit/ProgressBar.py | 29 +- utils/lit/lit/ShCommands.py | 42 +- utils/lit/lit/ShUtil.py | 50 +- utils/lit/lit/Test.py | 167 +- utils/lit/lit/TestFormats.py | 226 - utils/lit/lit/TestRunner.py | 247 +- utils/lit/lit/TestingConfig.py | 184 +- utils/lit/lit/Util.py | 141 - utils/lit/lit/__init__.py | 5 +- utils/lit/lit/discovery.py | 32 +- utils/lit/lit/formats/__init__.py | 4 + utils/lit/lit/formats/base.py | 118 + utils/lit/lit/formats/googletest.py | 114 + utils/lit/lit/formats/shtest.py | 12 + utils/lit/lit/main.py | 391 +- utils/lit/lit/run.py | 277 + utils/lit/lit/util.py | 169 + utils/lit/setup.py | 9 +- utils/lit/tests/Inputs/discovery/lit.cfg | 4 + .../tests/Inputs/discovery/subdir/lit.local.cfg | 3 + utils/lit/tests/Inputs/discovery/subsuite/lit.cfg | 1 + .../tests/Inputs/exec-discovery-in-tree/lit.cfg | 4 +- .../Inputs/exec-discovery-in-tree/obj/lit.site.cfg | 2 +- utils/lit/tests/Inputs/exec-discovery/lit.site.cfg | 2 +- .../Inputs/googletest-format/DummySubDir/OneTest | 34 + utils/lit/tests/Inputs/googletest-format/lit.cfg | 3 + utils/lit/tests/Inputs/progress-bar/lit.cfg | 1 + utils/lit/tests/Inputs/shtest-format/argv0.txt | 6 + .../Inputs/shtest-format/external_shell/fail.txt | 2 + .../external_shell/fail_with_bad_encoding.txt | 5 + .../shtest-format/external_shell/lit.local.cfg | 1 + .../external_shell/write-bad-encoding.sh | 3 + utils/lit/tests/Inputs/shtest-format/fail.txt | 1 + utils/lit/tests/Inputs/shtest-format/lit.cfg | 1 + utils/lit/tests/Inputs/shtest-shell/lit.cfg | 1 + utils/lit/tests/Inputs/test-data/lit.cfg | 44 + utils/lit/tests/Inputs/test-data/metrics.ini | 7 + utils/lit/tests/Inputs/unittest-adaptor/lit.cfg | 1 + utils/lit/tests/discovery.py | 51 +- utils/lit/tests/googletest-format.py | 20 + utils/lit/tests/lit.cfg | 15 +- utils/lit/tests/shell-parsing.py | 2 +- utils/lit/tests/shtest-encoding.py | 3 + utils/lit/tests/shtest-format.py | 44 +- utils/lit/tests/test-data.py | 12 + utils/lit/tests/test-output.py | 21 + utils/lit/tests/unittest-adaptor.py | 2 +- utils/llvm-build/llvmbuild/__init__.py | 2 +- utils/llvm-build/llvmbuild/componentinfo.py | 93 +- utils/llvm-build/llvmbuild/main.py | 122 +- utils/llvm-build/llvmbuild/util.py | 2 +- utils/llvm-lit/CMakeLists.txt | 8 - utils/not/CMakeLists.txt | 2 +- utils/not/not.cpp | 24 +- utils/profile.pl | 74 - utils/release/export.sh | 83 + utils/release/tag.sh | 7 +- utils/release/test-release.sh | 97 +- utils/test_debuginfo.pl | 19 +- utils/unittest/CMakeLists.txt | 13 +- utils/unittest/googletest/Makefile | 3 +- utils/unittest/googletest/README.LLVM | 16 +- utils/unittest/googletest/gtest-all.cc | 48 - utils/unittest/googletest/gtest-death-test.cc | 1233 - utils/unittest/googletest/gtest-filepath.cc | 378 - utils/unittest/googletest/gtest-port.cc | 750 - utils/unittest/googletest/gtest-printers.cc | 356 - utils/unittest/googletest/gtest-test-part.cc | 110 - utils/unittest/googletest/gtest-typed-test.cc | 110 - utils/unittest/googletest/gtest.cc | 4866 ---- .../googletest/include/gtest/gtest-test-part.h | 2 +- utils/unittest/googletest/include/gtest/gtest.h | 5 +- .../gtest/internal/gtest-death-test-internal.h | 4 +- .../include/gtest/internal/gtest-internal-inl.h | 1037 - .../include/gtest/internal/gtest-internal.h | 3 +- .../include/gtest/internal/gtest-param-util.h | 2 +- .../googletest/include/gtest/internal/gtest-port.h | 4 +- utils/unittest/googletest/src/gtest-all.cc | 48 + utils/unittest/googletest/src/gtest-death-test.cc | 1239 + utils/unittest/googletest/src/gtest-filepath.cc | 378 + utils/unittest/googletest/src/gtest-internal-inl.h | 1037 + utils/unittest/googletest/src/gtest-port.cc | 764 + utils/unittest/googletest/src/gtest-printers.cc | 356 + utils/unittest/googletest/src/gtest-test-part.cc | 110 + utils/unittest/googletest/src/gtest-typed-test.cc | 110 + utils/unittest/googletest/src/gtest.cc | 4876 ++++ utils/vim/llvm.vim | 44 +- utils/yaml-bench/YAMLBench.cpp | 22 +- 7068 files changed, 484753 insertions(+), 168285 deletions(-) create mode 100644 .clang-format create mode 100644 bindings/ocaml/backends/META.llvm_backend.in create mode 100644 bindings/ocaml/backends/Makefile create mode 100644 bindings/ocaml/backends/Makefile.common create mode 100644 bindings/ocaml/backends/backend_ocaml.c create mode 100644 bindings/ocaml/backends/llvm_backend.ml.in create mode 100644 bindings/ocaml/backends/llvm_backend.mli.in create mode 100644 bindings/ocaml/irreader/Makefile create mode 100644 bindings/ocaml/irreader/irreader_ocaml.c create mode 100644 bindings/ocaml/irreader/llvm_irreader.ml create mode 100644 bindings/ocaml/irreader/llvm_irreader.mli create mode 100644 bindings/ocaml/linker/Makefile create mode 100644 bindings/ocaml/linker/linker_ocaml.c create mode 100644 bindings/ocaml/linker/llvm_linker.ml create mode 100644 bindings/ocaml/linker/llvm_linker.mli create mode 100644 bindings/ocaml/transforms/passmgr_builder/Makefile create mode 100644 bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml create mode 100644 bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli create mode 100644 bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c create mode 100644 bindings/ocaml/transforms/vectorize/Makefile create mode 100644 bindings/ocaml/transforms/vectorize/llvm_vectorize.ml create mode 100644 bindings/ocaml/transforms/vectorize/llvm_vectorize.mli create mode 100644 bindings/ocaml/transforms/vectorize/vectorize_ocaml.c create mode 100644 bindings/python/llvm/bit_reader.py create mode 100644 bindings/python/llvm/tests/test.bc create mode 100644 bindings/python/llvm/tests/test_bitreader.py create mode 100644 bindings/python/llvm/tests/test_file create mode 100644 cmake/nsis_logo.bmp create mode 100644 docs/CMakeLists.txt delete mode 100644 docs/CommandGuide/llvm-ranlib.rst create mode 100644 docs/HowToCrossCompileLLVM.rst create mode 100644 docs/MCJIT-creation.png create mode 100644 docs/MCJIT-dyld-load.png create mode 100644 docs/MCJIT-engine-builder.png create mode 100644 docs/MCJIT-load-object.png create mode 100644 docs/MCJIT-load.png create mode 100644 docs/MCJIT-resolve-relocations.png create mode 100644 docs/MCJITDesignAndImplementation.rst create mode 100644 docs/ReleaseProcess.rst create mode 100644 examples/Kaleidoscope/MCJIT/README.txt create mode 100644 examples/Kaleidoscope/MCJIT/cached/Makefile create mode 100644 examples/Kaleidoscope/MCJIT/cached/README.txt create mode 100644 examples/Kaleidoscope/MCJIT/cached/genk-timing.py create mode 100644 examples/Kaleidoscope/MCJIT/cached/split-lib.py create mode 100644 examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp create mode 100644 examples/Kaleidoscope/MCJIT/cached/toy.cpp create mode 100644 examples/Kaleidoscope/MCJIT/complete/Makefile create mode 100644 examples/Kaleidoscope/MCJIT/complete/README.txt create mode 100644 examples/Kaleidoscope/MCJIT/complete/genk-timing.py create mode 100644 examples/Kaleidoscope/MCJIT/complete/split-lib.py create mode 100644 examples/Kaleidoscope/MCJIT/complete/toy.cpp create mode 100644 examples/Kaleidoscope/MCJIT/initial/Makefile create mode 100644 examples/Kaleidoscope/MCJIT/initial/README.txt create mode 100644 examples/Kaleidoscope/MCJIT/initial/toy.cpp create mode 100644 examples/Kaleidoscope/MCJIT/lazy/Makefile create mode 100644 examples/Kaleidoscope/MCJIT/lazy/README.txt create mode 100644 examples/Kaleidoscope/MCJIT/lazy/genk-timing.py create mode 100644 examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp create mode 100644 examples/Kaleidoscope/MCJIT/lazy/toy.cpp create mode 100644 include/llvm-c/IRReader.h create mode 100644 include/llvm-c/Support.h delete mode 100644 include/llvm/ADT/NullablePtr.h create mode 100644 include/llvm/ADT/polymorphic_ptr.h create mode 100644 include/llvm/Analysis/CFG.h delete mode 100644 include/llvm/Analysis/PathNumbering.h delete mode 100644 include/llvm/Analysis/PathProfileInfo.h delete mode 100644 include/llvm/Analysis/ProfileDataLoader.h delete mode 100644 include/llvm/Analysis/ProfileDataTypes.h delete mode 100644 include/llvm/Analysis/ProfileInfo.h delete mode 100644 include/llvm/Analysis/ProfileInfoLoader.h delete mode 100644 include/llvm/Analysis/ProfileInfoTypes.h delete mode 100644 include/llvm/Bitcode/Archive.h create mode 100644 include/llvm/CodeGen/LiveRegUnits.h create mode 100644 include/llvm/CodeGen/StackMaps.h create mode 100644 include/llvm/CodeGen/StackProtector.h create mode 100644 include/llvm/ExecutionEngine/RTDyldMemoryManager.h create mode 100644 include/llvm/IR/IntrinsicsAArch64.td create mode 100644 include/llvm/IR/LegacyPassManager.h create mode 100644 include/llvm/IR/LegacyPassManagers.h create mode 100644 include/llvm/IR/PassManager.h create mode 100644 include/llvm/LTO/LTOCodeGenerator.h create mode 100644 include/llvm/LTO/LTOModule.h create mode 100644 include/llvm/MC/MCAsmInfoELF.h create mode 100644 include/llvm/MC/MCExternalSymbolizer.h create mode 100644 include/llvm/MC/MCFunction.h create mode 100644 include/llvm/MC/MCModuleYAML.h create mode 100644 include/llvm/MC/MCObjectDisassembler.h create mode 100644 include/llvm/MC/MCObjectSymbolizer.h create mode 100644 include/llvm/MC/MCRelocationInfo.h create mode 100644 include/llvm/MC/MCSymbolizer.h create mode 100644 include/llvm/Object/COFFYAML.h create mode 100644 include/llvm/Object/ELFObjectFile.h create mode 100644 include/llvm/Object/ELFTypes.h create mode 100644 include/llvm/Object/ELFYAML.h delete mode 100644 include/llvm/Object/MachOFormat.h create mode 100644 include/llvm/Object/MachOUniversal.h create mode 100644 include/llvm/Object/YAML.h delete mode 100644 include/llvm/PassManagers.h delete mode 100644 include/llvm/Support/IntegersSubset.h delete mode 100644 include/llvm/Support/IntegersSubsetMapping.h create mode 100644 include/llvm/Support/MD5.h delete mode 100644 include/llvm/Support/PathV1.h delete mode 100644 include/llvm/Support/PathV2.h create mode 100644 include/llvm/Support/StringRefMemoryObject.h create mode 100644 include/llvm/Support/Unicode.h create mode 100644 include/llvm/Support/UnicodeCharRanges.h create mode 100644 include/llvm/TableGen/StringToOffsetTable.h delete mode 100644 include/llvm/Transforms/Utils/BlackList.h create mode 100644 include/llvm/Transforms/Utils/GlobalStatus.h create mode 100644 include/llvm/Transforms/Utils/LoopUtils.h create mode 100644 include/llvm/Transforms/Utils/SpecialCaseList.h create mode 100644 lib/Analysis/CFG.cpp create mode 100644 lib/Analysis/Delinearization.cpp delete mode 100644 lib/Analysis/PathNumbering.cpp delete mode 100644 lib/Analysis/PathProfileInfo.cpp delete mode 100644 lib/Analysis/PathProfileVerifier.cpp delete mode 100644 lib/Analysis/ProfileDataLoader.cpp delete mode 100644 lib/Analysis/ProfileDataLoaderPass.cpp delete mode 100644 lib/Analysis/ProfileEstimatorPass.cpp delete mode 100644 lib/Analysis/ProfileInfo.cpp delete mode 100644 lib/Analysis/ProfileInfoLoader.cpp delete mode 100644 lib/Analysis/ProfileInfoLoaderPass.cpp delete mode 100644 lib/Analysis/ProfileVerifierPass.cpp delete mode 100644 lib/Archive/Archive.cpp delete mode 100644 lib/Archive/ArchiveInternals.h delete mode 100644 lib/Archive/ArchiveReader.cpp delete mode 100644 lib/Archive/ArchiveWriter.cpp delete mode 100644 lib/Archive/CMakeLists.txt delete mode 100644 lib/Archive/LLVMBuild.txt delete mode 100644 lib/Archive/Makefile create mode 100644 lib/CodeGen/AsmPrinter/DIEHash.cpp create mode 100644 lib/CodeGen/AsmPrinter/DIEHash.h create mode 100644 lib/CodeGen/LiveRegUnits.cpp delete mode 100644 lib/CodeGen/SelectionDAG/SDNodeOrdering.h delete mode 100644 lib/CodeGen/ShrinkWrapping.cpp create mode 100644 lib/CodeGen/StackMaps.cpp delete mode 100644 lib/CodeGen/StrongPHIElimination.cpp delete mode 100644 lib/DebugInfo/DWARFAttribute.h create mode 100644 lib/DebugInfo/DWARFDebugLoc.cpp create mode 100644 lib/DebugInfo/DWARFDebugLoc.h create mode 100644 lib/DebugInfo/DWARFTypeUnit.cpp create mode 100644 lib/DebugInfo/DWARFTypeUnit.h create mode 100644 lib/DebugInfo/DWARFUnit.cpp create mode 100644 lib/DebugInfo/DWARFUnit.h delete mode 100644 lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp delete mode 100644 lib/ExecutionEngine/JIT/JITDwarfEmitter.h create mode 100644 lib/ExecutionEngine/RTDyldMemoryManager.cpp create mode 100644 lib/IR/AsmWriter.h create mode 100644 lib/IR/LegacyPassManager.cpp create mode 100644 lib/LTO/CMakeLists.txt create mode 100644 lib/LTO/LLVMBuild.txt create mode 100644 lib/LTO/LTOCodeGenerator.cpp create mode 100644 lib/LTO/LTOModule.cpp create mode 100644 lib/LTO/Makefile create mode 100644 lib/MC/MCAsmInfoELF.cpp create mode 100644 lib/MC/MCExternalSymbolizer.cpp create mode 100644 lib/MC/MCFunction.cpp create mode 100644 lib/MC/MCModuleYAML.cpp create mode 100644 lib/MC/MCObjectDisassembler.cpp create mode 100644 lib/MC/MCObjectSymbolizer.cpp create mode 100644 lib/MC/MCRelocationInfo.cpp create mode 100644 lib/MC/MCSymbolizer.cpp create mode 100644 lib/Object/COFFYAML.cpp create mode 100644 lib/Object/ELF.cpp create mode 100644 lib/Object/ELFYAML.cpp create mode 100644 lib/Object/MachOUniversal.cpp create mode 100644 lib/Object/YAML.cpp delete mode 100644 lib/Support/LocaleGeneric.inc delete mode 100644 lib/Support/LocaleWindows.inc delete mode 100644 lib/Support/LocaleXlocale.inc create mode 100644 lib/Support/MD5.cpp delete mode 100644 lib/Support/PathV2.cpp create mode 100644 lib/Support/StringRefMemoryObject.cpp create mode 100644 lib/Support/Unicode.cpp delete mode 100644 lib/Support/Unix/PathV2.inc delete mode 100644 lib/Support/Windows/PathV2.inc create mode 100644 lib/Target/AArch64/AArch64InstrNEON.td create mode 100644 lib/Target/ARM/ARMFPUName.def create mode 100644 lib/Target/ARM/ARMFPUName.h create mode 100644 lib/Target/ARM/ARMFeatures.h delete mode 100644 lib/Target/ARM/MCTargetDesc/ARMELFStreamer.h create mode 100644 lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp create mode 100644 lib/Target/Hexagon/HexagonCopyToCombine.cpp create mode 100644 lib/Target/Hexagon/HexagonMachineFunctionInfo.cpp create mode 100644 lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp delete mode 100644 lib/Target/MBlaze/AsmParser/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/AsmParser/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp delete mode 100644 lib/Target/MBlaze/AsmParser/Makefile delete mode 100644 lib/Target/MBlaze/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/Disassembler/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/Disassembler/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp delete mode 100644 lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h delete mode 100644 lib/Target/MBlaze/Disassembler/Makefile delete mode 100644 lib/Target/MBlaze/InstPrinter/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/InstPrinter/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp delete mode 100644 lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h delete mode 100644 lib/Target/MBlaze/InstPrinter/Makefile delete mode 100644 lib/Target/MBlaze/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/MBlaze.h delete mode 100644 lib/Target/MBlaze/MBlaze.td delete mode 100644 lib/Target/MBlaze/MBlazeAsmPrinter.cpp delete mode 100644 lib/Target/MBlaze/MBlazeCallingConv.td delete mode 100644 lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp delete mode 100644 lib/Target/MBlaze/MBlazeFrameLowering.cpp delete mode 100644 lib/Target/MBlaze/MBlazeFrameLowering.h delete mode 100644 lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp delete mode 100644 lib/Target/MBlaze/MBlazeISelLowering.cpp delete mode 100644 lib/Target/MBlaze/MBlazeISelLowering.h delete mode 100644 lib/Target/MBlaze/MBlazeInstrFPU.td delete mode 100644 lib/Target/MBlaze/MBlazeInstrFSL.td delete mode 100644 lib/Target/MBlaze/MBlazeInstrFormats.td delete mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.cpp delete mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.h delete mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.td delete mode 100644 lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp delete mode 100644 lib/Target/MBlaze/MBlazeIntrinsicInfo.h delete mode 100644 lib/Target/MBlaze/MBlazeIntrinsics.td delete mode 100644 lib/Target/MBlaze/MBlazeMCInstLower.cpp delete mode 100644 lib/Target/MBlaze/MBlazeMCInstLower.h delete mode 100644 lib/Target/MBlaze/MBlazeMachineFunction.cpp delete mode 100644 lib/Target/MBlaze/MBlazeMachineFunction.h delete mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.cpp delete mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.h delete mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.td delete mode 100644 lib/Target/MBlaze/MBlazeRelocations.h delete mode 100644 lib/Target/MBlaze/MBlazeSchedule.td delete mode 100644 lib/Target/MBlaze/MBlazeSchedule3.td delete mode 100644 lib/Target/MBlaze/MBlazeSchedule5.td delete mode 100644 lib/Target/MBlaze/MBlazeSelectionDAGInfo.cpp delete mode 100644 lib/Target/MBlaze/MBlazeSelectionDAGInfo.h delete mode 100644 lib/Target/MBlaze/MBlazeSubtarget.cpp delete mode 100644 lib/Target/MBlaze/MBlazeSubtarget.h delete mode 100644 lib/Target/MBlaze/MBlazeTargetMachine.cpp delete mode 100644 lib/Target/MBlaze/MBlazeTargetMachine.h delete mode 100644 lib/Target/MBlaze/MBlazeTargetObjectFile.cpp delete mode 100644 lib/Target/MBlaze/MBlazeTargetObjectFile.h delete mode 100644 lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/MCTargetDesc/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeELFObjectWriter.cpp delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp delete mode 100644 lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h delete mode 100644 lib/Target/MBlaze/MCTargetDesc/Makefile delete mode 100644 lib/Target/MBlaze/Makefile delete mode 100644 lib/Target/MBlaze/TODO delete mode 100644 lib/Target/MBlaze/TargetInfo/CMakeLists.txt delete mode 100644 lib/Target/MBlaze/TargetInfo/LLVMBuild.txt delete mode 100644 lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp delete mode 100644 lib/Target/MBlaze/TargetInfo/Makefile delete mode 100644 lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.cpp delete mode 100644 lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.h delete mode 100644 lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp delete mode 100644 lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h create mode 100644 lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp create mode 100644 lib/Target/Mips/MSA.txt create mode 100644 lib/Target/Mips/Mips16HardFloat.cpp create mode 100644 lib/Target/Mips/Mips16HardFloat.h create mode 100644 lib/Target/Mips/MipsMSAInstrFormats.td create mode 100644 lib/Target/Mips/MipsMSAInstrInfo.td create mode 100644 lib/Target/Mips/MipsTargetStreamer.h create mode 100644 lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h create mode 100644 lib/Target/NVPTX/NVPTXMCExpr.cpp create mode 100644 lib/Target/NVPTX/NVPTXMCExpr.h delete mode 100644 lib/Target/NVPTX/NVPTXNumRegisters.h create mode 100644 lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp create mode 100644 lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp create mode 100644 lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h create mode 100644 lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp create mode 100644 lib/Target/PowerPC/PPCFastISel.cpp create mode 100644 lib/Target/PowerPC/PPCTargetObjectFile.cpp create mode 100644 lib/Target/PowerPC/PPCTargetObjectFile.h create mode 100644 lib/Target/PowerPC/PPCTargetStreamer.h create mode 100644 lib/Target/R600/AMDGPUISelDAGToDAG.cpp delete mode 100644 lib/Target/R600/AMDGPUIndirectAddressing.cpp delete mode 100644 lib/Target/R600/AMDGPUStructurizeCFG.cpp create mode 100644 lib/Target/R600/AMDGPUTargetTransformInfo.cpp delete mode 100644 lib/Target/R600/AMDIL.h delete mode 100644 lib/Target/R600/AMDIL7XXDevice.cpp delete mode 100644 lib/Target/R600/AMDIL7XXDevice.h delete mode 100644 lib/Target/R600/AMDILDevice.cpp delete mode 100644 lib/Target/R600/AMDILDevice.h delete mode 100644 lib/Target/R600/AMDILDeviceInfo.cpp delete mode 100644 lib/Target/R600/AMDILDeviceInfo.h delete mode 100644 lib/Target/R600/AMDILDevices.h delete mode 100644 lib/Target/R600/AMDILEvergreenDevice.cpp delete mode 100644 lib/Target/R600/AMDILEvergreenDevice.h delete mode 100644 lib/Target/R600/AMDILISelDAGToDAG.cpp delete mode 100644 lib/Target/R600/AMDILNIDevice.cpp delete mode 100644 lib/Target/R600/AMDILNIDevice.h delete mode 100644 lib/Target/R600/AMDILSIDevice.cpp delete mode 100644 lib/Target/R600/AMDILSIDevice.h create mode 100644 lib/Target/R600/MCTargetDesc/AMDGPUMCCodeEmitter.cpp create mode 100644 lib/Target/R600/R600ClauseMergePass.cpp create mode 100644 lib/Target/R600/R600InstrFormats.td create mode 100644 lib/Target/R600/R600OptimizeVectorRegisters.cpp create mode 100644 lib/Target/R600/R600TextureIntrinsicsReplacer.cpp create mode 100644 lib/Target/R600/SIFixSGPRCopies.cpp create mode 100644 lib/Target/R600/SITypeRewriter.cpp delete mode 100644 lib/Target/Sparc/FPMover.cpp create mode 100644 lib/Target/Sparc/SparcCodeEmitter.cpp create mode 100644 lib/Target/Sparc/SparcJITInfo.cpp create mode 100644 lib/Target/Sparc/SparcJITInfo.h create mode 100644 lib/Target/Sparc/SparcRelocations.h create mode 100644 lib/Target/SystemZ/Disassembler/CMakeLists.txt create mode 100644 lib/Target/SystemZ/Disassembler/LLVMBuild.txt create mode 100644 lib/Target/SystemZ/Disassembler/Makefile create mode 100644 lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp create mode 100644 lib/Target/SystemZ/SystemZElimCompare.cpp create mode 100644 lib/Target/SystemZ/SystemZLongBranch.cpp create mode 100644 lib/Target/SystemZ/SystemZMachineFunctionInfo.cpp create mode 100644 lib/Target/SystemZ/SystemZProcessors.td create mode 100644 lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp create mode 100644 lib/Target/SystemZ/SystemZSelectionDAGInfo.h create mode 100644 lib/Target/SystemZ/SystemZShortenInst.cpp create mode 100644 lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp create mode 100644 lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp create mode 100644 lib/Target/X86/X86CallingConv.h create mode 100644 lib/Target/X86/X86InstrAVX512.td create mode 100644 lib/Target/X86/X86ScheduleSLM.td create mode 100644 lib/Target/XCore/XCoreTargetTransformInfo.cpp delete mode 100644 lib/Transforms/Instrumentation/BlackList.cpp create mode 100644 lib/Transforms/Instrumentation/DataFlowSanitizer.cpp create mode 100644 lib/Transforms/Instrumentation/DebugIR.cpp create mode 100644 lib/Transforms/Instrumentation/DebugIR.h delete mode 100644 lib/Transforms/Instrumentation/EdgeProfiling.cpp delete mode 100644 lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp delete mode 100644 lib/Transforms/Instrumentation/PathProfiling.cpp delete mode 100644 lib/Transforms/Instrumentation/ProfilingUtils.cpp delete mode 100644 lib/Transforms/Instrumentation/ProfilingUtils.h create mode 100644 lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h delete mode 100644 lib/Transforms/Scalar/BasicBlockPlacement.cpp create mode 100644 lib/Transforms/Scalar/FlattenCFGPass.cpp create mode 100644 lib/Transforms/Scalar/LoopRerollPass.cpp create mode 100644 lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp create mode 100644 lib/Transforms/Scalar/SampleProfile.cpp delete mode 100644 lib/Transforms/Scalar/SimplifyLibCalls.cpp create mode 100644 lib/Transforms/Scalar/StructurizeCFG.cpp create mode 100644 lib/Transforms/Utils/FlattenCFG.cpp create mode 100644 lib/Transforms/Utils/GlobalStatus.cpp create mode 100644 lib/Transforms/Utils/SpecialCaseList.cpp delete mode 100644 lib/Transforms/Vectorize/VecUtils.cpp delete mode 100644 lib/Transforms/Vectorize/VecUtils.h delete mode 100644 runtime/CMakeLists.txt delete mode 100644 runtime/LLVMBuild.txt delete mode 100644 runtime/Makefile delete mode 100644 runtime/README.txt delete mode 100644 runtime/libprofile/BasicBlockTracing.c delete mode 100644 runtime/libprofile/CMakeLists.txt delete mode 100644 runtime/libprofile/CommonProfiling.c delete mode 100644 runtime/libprofile/EdgeProfiling.c delete mode 100644 runtime/libprofile/Makefile delete mode 100644 runtime/libprofile/OptimalEdgeProfiling.c delete mode 100644 runtime/libprofile/PathProfiling.c delete mode 100644 runtime/libprofile/Profiling.h create mode 100644 test/.clang-format delete mode 100644 test/Analysis/BasicAA/lit.local.cfg create mode 100644 test/Analysis/BasicAA/noalias-param.ll delete mode 100644 test/Analysis/BlockFrequencyInfo/lit.local.cfg delete mode 100644 test/Analysis/BranchProbabilityInfo/lit.local.cfg delete mode 100644 test/Analysis/CallGraph/lit.local.cfg create mode 100644 test/Analysis/CostModel/X86/div.ll create mode 100644 test/Analysis/CostModel/X86/reduction.ll delete mode 100644 test/Analysis/CostModel/lit.local.cfg create mode 100644 test/Analysis/Delinearization/a.ll create mode 100644 test/Analysis/Delinearization/himeno_1.ll create mode 100644 test/Analysis/Delinearization/himeno_2.ll create mode 100644 test/Analysis/Delinearization/lit.local.cfg create mode 100644 test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll create mode 100644 test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll create mode 100644 test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll create mode 100644 test/Analysis/Delinearization/multidim_only_ivs_2d.ll create mode 100644 test/Analysis/Delinearization/multidim_only_ivs_2d_nested.ll create mode 100644 test/Analysis/Delinearization/multidim_only_ivs_3d.ll create mode 100644 test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll create mode 100644 test/Analysis/DependenceAnalysis/Invariant.ll delete mode 100644 test/Analysis/DependenceAnalysis/lit.local.cfg delete mode 100644 test/Analysis/Dominators/lit.local.cfg delete mode 100644 test/Analysis/GlobalsModRef/lit.local.cfg create mode 100644 test/Analysis/Lint/check-zero-divide.ll create mode 100644 test/Analysis/Lint/lit.local.cfg delete mode 100644 test/Analysis/LoopInfo/lit.local.cfg delete mode 100644 test/Analysis/MemoryDependenceAnalysis/lit.local.cfg delete mode 100644 test/Analysis/PostDominators/lit.local.cfg delete mode 100644 test/Analysis/Profiling/edge-profiling.ll delete mode 100644 test/Analysis/Profiling/lit.local.cfg delete mode 100644 test/Analysis/Profiling/load-branch-weights-ifs.ll delete mode 100644 test/Analysis/Profiling/load-branch-weights-loops.ll delete mode 100644 test/Analysis/Profiling/load-branch-weights-switches.ll delete mode 100644 test/Analysis/Profiling/profiling-tool-chain.ll delete mode 100644 test/Analysis/RegionInfo/lit.local.cfg delete mode 100644 test/Analysis/ScalarEvolution/lit.local.cfg create mode 100644 test/Analysis/ScalarEvolution/max-trip-count-address-space.ll create mode 100644 test/Analysis/TypeBasedAliasAnalysis/PR17620.ll delete mode 100644 test/Analysis/TypeBasedAliasAnalysis/lit.local.cfg delete mode 100644 test/Archive/GNU.a delete mode 100644 test/Archive/IsNAN.o delete mode 100644 test/Archive/MacOSX.a delete mode 100644 test/Archive/README.txt delete mode 100644 test/Archive/SVR4.a delete mode 100644 test/Archive/check_binary_output.ll delete mode 100644 test/Archive/evenlen delete mode 100644 test/Archive/extract.ll delete mode 100644 test/Archive/lit.local.cfg delete mode 100644 test/Archive/oddlen delete mode 100644 test/Archive/toc_GNU.ll delete mode 100644 test/Archive/toc_MacOSX.ll delete mode 100644 test/Archive/toc_SVR4.ll delete mode 100644 test/Archive/toc_xpg4.ll delete mode 100644 test/Archive/very_long_bytecode_file_name.bc delete mode 100644 test/Archive/xpg4.a create mode 100644 test/Assembler/attribute-builtin.ll delete mode 100644 test/Assembler/lit.local.cfg create mode 100644 test/Bindings/Ocaml/irreader.ml create mode 100644 test/Bindings/Ocaml/linker.ml create mode 100644 test/Bindings/Ocaml/passmgr_builder.ml create mode 100644 test/Bindings/Ocaml/vectorize_opts.ml create mode 100644 test/Bindings/llvm-c/calc.test create mode 100644 test/Bindings/llvm-c/disassemble.test create mode 100644 test/Bindings/llvm-c/functions.ll create mode 100644 test/Bindings/llvm-c/globals.ll create mode 100644 test/Bindings/llvm-c/lit.local.cfg delete mode 100644 test/Bitcode/2012-05-07-SwitchInstRangesSupport.ll create mode 100644 test/Bitcode/attributes-3.3.ll create mode 100644 test/Bitcode/attributes-3.3.ll.bc create mode 100644 test/Bitcode/case-ranges-3.3.ll create mode 100644 test/Bitcode/case-ranges-3.3.ll.bc create mode 100644 test/Bitcode/drop-debug-info.ll create mode 100644 test/Bitcode/invalid.ll create mode 100644 test/Bitcode/invalid.ll.bc delete mode 100644 test/Bitcode/lit.local.cfg create mode 100644 test/Bitcode/select.ll create mode 100644 test/Bitcode/upgrade-tbaa.ll delete mode 100644 test/BugPoint/lit.local.cfg delete mode 100644 test/CodeGen/AArch64/adrp-relocation.ll create mode 100644 test/CodeGen/AArch64/complex-copy-noneon.ll delete mode 100644 test/CodeGen/AArch64/elf-extern.ll create mode 100644 test/CodeGen/AArch64/frameaddr.ll create mode 100644 test/CodeGen/AArch64/large-consts.ll delete mode 100644 test/CodeGen/AArch64/logical_shifted_reg.s create mode 100644 test/CodeGen/AArch64/movw-shift-encoding.ll create mode 100644 test/CodeGen/AArch64/neon-2velem-high.ll create mode 100644 test/CodeGen/AArch64/neon-2velem.ll create mode 100644 test/CodeGen/AArch64/neon-3vdiff.ll create mode 100644 test/CodeGen/AArch64/neon-aba-abd.ll create mode 100644 test/CodeGen/AArch64/neon-across.ll create mode 100644 test/CodeGen/AArch64/neon-add-pairwise.ll create mode 100644 test/CodeGen/AArch64/neon-add-sub.ll create mode 100644 test/CodeGen/AArch64/neon-bitcast.ll create mode 100644 test/CodeGen/AArch64/neon-bitwise-instructions.ll create mode 100644 test/CodeGen/AArch64/neon-bsl.ll create mode 100644 test/CodeGen/AArch64/neon-compare-instructions.ll create mode 100644 test/CodeGen/AArch64/neon-copy.ll create mode 100644 test/CodeGen/AArch64/neon-crypto.ll create mode 100644 test/CodeGen/AArch64/neon-diagnostics.ll create mode 100644 test/CodeGen/AArch64/neon-extract.ll create mode 100644 test/CodeGen/AArch64/neon-facge-facgt.ll create mode 100644 test/CodeGen/AArch64/neon-fma.ll create mode 100644 test/CodeGen/AArch64/neon-frsqrt-frecp.ll create mode 100644 test/CodeGen/AArch64/neon-halving-add-sub.ll create mode 100644 test/CodeGen/AArch64/neon-max-min-pairwise.ll create mode 100644 test/CodeGen/AArch64/neon-max-min.ll create mode 100644 test/CodeGen/AArch64/neon-misc-scalar.ll create mode 100644 test/CodeGen/AArch64/neon-misc.ll create mode 100644 test/CodeGen/AArch64/neon-mla-mls.ll create mode 100644 test/CodeGen/AArch64/neon-mov.ll create mode 100644 test/CodeGen/AArch64/neon-mul-div.ll create mode 100644 test/CodeGen/AArch64/neon-perm.ll create mode 100644 test/CodeGen/AArch64/neon-rounding-halving-add.ll create mode 100644 test/CodeGen/AArch64/neon-rounding-shift.ll create mode 100644 test/CodeGen/AArch64/neon-saturating-add-sub.ll create mode 100644 test/CodeGen/AArch64/neon-saturating-rounding-shift.ll create mode 100644 test/CodeGen/AArch64/neon-saturating-shift.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-abs.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-add-sub.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-by-elem-fma.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-by-elem-mul.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-compare.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-copy.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-cvt.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-extract-narrow.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-fabd.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-fcvt.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-fp-compare.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-mul.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-neg.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-recip.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-reduce-pairwise.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-rounding-shift.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-saturating-add-sub.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-saturating-rounding-shift.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-saturating-shift.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-shift-imm.ll create mode 100644 test/CodeGen/AArch64/neon-scalar-shift.ll create mode 100644 test/CodeGen/AArch64/neon-shift-left-long.ll create mode 100644 test/CodeGen/AArch64/neon-shift.ll create mode 100644 test/CodeGen/AArch64/neon-simd-ldst-multi-elem.ll create mode 100644 test/CodeGen/AArch64/neon-simd-ldst-one.ll create mode 100644 test/CodeGen/AArch64/neon-simd-ldst.ll create mode 100644 test/CodeGen/AArch64/neon-simd-post-ldst-multi-elem.ll create mode 100644 test/CodeGen/AArch64/neon-simd-post-ldst-one.ll create mode 100644 test/CodeGen/AArch64/neon-simd-shift.ll create mode 100644 test/CodeGen/AArch64/neon-simd-tbl.ll create mode 100644 test/CodeGen/AArch64/neon-simd-vget.ll create mode 100644 test/CodeGen/AArch64/regress-fp128-livein.ll create mode 100644 test/CodeGen/AArch64/returnaddr.ll delete mode 100644 test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll delete mode 100644 test/CodeGen/ARM/2010-11-30-reloc-movt.ll create mode 100644 test/CodeGen/ARM/2013-05-07-ByteLoadSameAddress.ll create mode 100644 test/CodeGen/ARM/2013-05-13-AAPCS-byval-padding.ll create mode 100644 test/CodeGen/ARM/2013-05-13-AAPCS-byval-padding2.ll create mode 100644 test/CodeGen/ARM/2013-05-13-DAGCombiner-undef-mask.ll create mode 100644 test/CodeGen/ARM/2013-05-31-char-shift-crash.ll create mode 100644 test/CodeGen/ARM/2013-06-03-ByVal-2Kbytes.ll create mode 100644 test/CodeGen/ARM/2013-07-29-vector-or-combine.ll create mode 100644 test/CodeGen/ARM/2013-10-11-select-stalls.ll create mode 100644 test/CodeGen/ARM/2013-11-08-inline-asm-neon-array.ll create mode 100644 test/CodeGen/ARM/addrspacecast.ll create mode 100644 test/CodeGen/ARM/atomic-ops-v8.ll create mode 100644 test/CodeGen/ARM/build-attributes-encoding.s create mode 100644 test/CodeGen/ARM/byval_load_align.ll create mode 100644 test/CodeGen/ARM/coalesce-dbgvalue.ll create mode 100644 test/CodeGen/ARM/constantfp.ll create mode 100644 test/CodeGen/ARM/copy-paired-reg.ll create mode 100644 test/CodeGen/ARM/darwin-eabi.ll create mode 100644 test/CodeGen/ARM/divmod-eabi.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-cantunwind.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-compact-pr0.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-compact-pr1.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-section-group.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-section.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc-sh_link.ll delete mode 100644 test/CodeGen/ARM/ehabi-mc.ll create mode 100644 test/CodeGen/ARM/ehabi.ll create mode 100644 test/CodeGen/ARM/emit-big-cst.ll create mode 100644 test/CodeGen/ARM/fast-isel-align.ll create mode 100644 test/CodeGen/ARM/fast-isel-ext.ll create mode 100644 test/CodeGen/ARM/fast-isel-load-store-verify.ll create mode 100644 test/CodeGen/ARM/fast-isel-vararg.ll create mode 100644 test/CodeGen/ARM/fast-tail-call.ll create mode 100644 test/CodeGen/ARM/fastisel-gep-promote-before-add.ll create mode 100644 test/CodeGen/ARM/fold-stack-adjust.ll create mode 100644 test/CodeGen/ARM/ifconv-kills.ll create mode 100644 test/CodeGen/ARM/ifconv-regmask.ll create mode 100644 test/CodeGen/ARM/indirectbr-3.ll create mode 100644 test/CodeGen/ARM/interrupt-attr.ll create mode 100644 test/CodeGen/ARM/intrinsics-crypto.ll create mode 100644 test/CodeGen/ARM/intrinsics-v8.ll create mode 100644 test/CodeGen/ARM/ldstrex.ll delete mode 100644 test/CodeGen/ARM/ldstrexd.ll create mode 100644 test/CodeGen/ARM/load-address-masked.ll create mode 100644 test/CodeGen/ARM/no-fpu.ll create mode 100644 test/CodeGen/ARM/noreturn.ll create mode 100644 test/CodeGen/ARM/optselect-regclass.ll create mode 100644 test/CodeGen/ARM/pic.ll create mode 100644 test/CodeGen/ARM/prefetch-thumb.ll create mode 100644 test/CodeGen/ARM/readcyclecounter.ll create mode 100644 test/CodeGen/ARM/returned-trunc-tail-calls.ll create mode 100644 test/CodeGen/ARM/section-name.ll create mode 100644 test/CodeGen/ARM/select-undef.ll create mode 100644 test/CodeGen/ARM/setcc-sentinals.ll create mode 100644 test/CodeGen/ARM/sincos.ll create mode 100644 test/CodeGen/ARM/stack-protector-bmovpcb_call.ll create mode 100644 test/CodeGen/ARM/struct-byval-frame-index.ll create mode 100644 test/CodeGen/ARM/struct_byval_arm_t1_t2.ll create mode 100644 test/CodeGen/ARM/swift-atomics.ll create mode 100644 test/CodeGen/ARM/swift-vldm.ll create mode 100644 test/CodeGen/ARM/unwind-init.ll create mode 100644 test/CodeGen/ARM/vcvt-v8.ll create mode 100644 test/CodeGen/ARM/vldm-liveness.ll create mode 100644 test/CodeGen/ARM/vldm-sched-a9.ll create mode 100644 test/CodeGen/ARM/vminmaxnm.ll create mode 100644 test/CodeGen/ARM/vsel.ll create mode 100644 test/CodeGen/ARM/warn-stack.ll delete mode 100644 test/CodeGen/Generic/lit.local.cfg create mode 100644 test/CodeGen/Hexagon/BranchPredict.ll create mode 100644 test/CodeGen/Hexagon/extload-combine.ll create mode 100644 test/CodeGen/Hexagon/packetize_cond_inst.ll create mode 100644 test/CodeGen/Hexagon/pred-gp.ll create mode 100644 test/CodeGen/Hexagon/pred-instrs.ll create mode 100644 test/CodeGen/Hexagon/split-const32-const64.ll create mode 100644 test/CodeGen/Hexagon/tail-call-trunc.ll create mode 100644 test/CodeGen/Hexagon/tfr-to-combine.ll delete mode 100644 test/CodeGen/MBlaze/DbgValueOtherTargets.test delete mode 100644 test/CodeGen/MBlaze/brind.ll delete mode 100644 test/CodeGen/MBlaze/callind.ll delete mode 100644 test/CodeGen/MBlaze/cc.ll delete mode 100644 test/CodeGen/MBlaze/div.ll delete mode 100644 test/CodeGen/MBlaze/fpu.ll delete mode 100644 test/CodeGen/MBlaze/fsl.ll delete mode 100644 test/CodeGen/MBlaze/imm.ll delete mode 100644 test/CodeGen/MBlaze/intr.ll delete mode 100644 test/CodeGen/MBlaze/jumptable.ll delete mode 100644 test/CodeGen/MBlaze/lit.local.cfg delete mode 100644 test/CodeGen/MBlaze/loop.ll delete mode 100644 test/CodeGen/MBlaze/mul.ll delete mode 100644 test/CodeGen/MBlaze/mul64.ll delete mode 100644 test/CodeGen/MBlaze/select.ll delete mode 100644 test/CodeGen/MBlaze/shift.ll delete mode 100644 test/CodeGen/MBlaze/svol.ll create mode 100644 test/CodeGen/MSP430/cc_args.ll create mode 100644 test/CodeGen/MSP430/cc_ret.ll create mode 100644 test/CodeGen/MSP430/jumptable.ll create mode 100644 test/CodeGen/MSP430/transient-stack-alignment.ll create mode 100644 test/CodeGen/Mips/2013-11-18-fp64-const0.ll create mode 100644 test/CodeGen/Mips/beqzc.ll create mode 100644 test/CodeGen/Mips/beqzc1.ll create mode 100644 test/CodeGen/Mips/blez_bgez.ll create mode 100644 test/CodeGen/Mips/brsize3.ll create mode 100644 test/CodeGen/Mips/brsize3a.ll create mode 100644 test/CodeGen/Mips/cmplarge.ll create mode 100644 test/CodeGen/Mips/const-mult.ll create mode 100644 test/CodeGen/Mips/const1.ll create mode 100644 test/CodeGen/Mips/const4a.ll create mode 100644 test/CodeGen/Mips/const6.ll create mode 100644 test/CodeGen/Mips/const6a.ll create mode 100644 test/CodeGen/Mips/ctlz.ll create mode 100644 test/CodeGen/Mips/disable-tail-merge.ll create mode 100644 test/CodeGen/Mips/dsp-vec-load-store.ll create mode 100644 test/CodeGen/Mips/emit-big-cst.ll create mode 100644 test/CodeGen/Mips/f16abs.ll create mode 100644 test/CodeGen/Mips/fixdfsf.ll create mode 100644 test/CodeGen/Mips/fp16instrinsmc.ll create mode 100644 test/CodeGen/Mips/fp16mix.ll create mode 100644 test/CodeGen/Mips/fptr2.ll create mode 100644 test/CodeGen/Mips/hf16call32.ll create mode 100644 test/CodeGen/Mips/hf16call32_body.ll create mode 100644 test/CodeGen/Mips/hf1_body.ll create mode 100644 test/CodeGen/Mips/hfptrcall.ll create mode 100644 test/CodeGen/Mips/int-to-float-conversion.ll create mode 100644 test/CodeGen/Mips/lazy-binding.ll create mode 100644 test/CodeGen/Mips/mips16_fpret.ll create mode 100644 test/CodeGen/Mips/mno-ldc1-sdc1.ll create mode 100644 test/CodeGen/Mips/msa/2r.ll create mode 100644 test/CodeGen/Mips/msa/2r_vector_scalar.ll create mode 100644 test/CodeGen/Mips/msa/2rf.ll create mode 100644 test/CodeGen/Mips/msa/2rf_exup.ll create mode 100644 test/CodeGen/Mips/msa/2rf_float_int.ll create mode 100644 test/CodeGen/Mips/msa/2rf_fq.ll create mode 100644 test/CodeGen/Mips/msa/2rf_int_float.ll create mode 100644 test/CodeGen/Mips/msa/2rf_tq.ll create mode 100644 test/CodeGen/Mips/msa/3r-a.ll create mode 100644 test/CodeGen/Mips/msa/3r-b.ll create mode 100644 test/CodeGen/Mips/msa/3r-c.ll create mode 100644 test/CodeGen/Mips/msa/3r-d.ll create mode 100644 test/CodeGen/Mips/msa/3r-i.ll create mode 100644 test/CodeGen/Mips/msa/3r-m.ll create mode 100644 test/CodeGen/Mips/msa/3r-p.ll create mode 100644 test/CodeGen/Mips/msa/3r-s.ll create mode 100644 test/CodeGen/Mips/msa/3r-v.ll create mode 100644 test/CodeGen/Mips/msa/3r_4r.ll create mode 100644 test/CodeGen/Mips/msa/3r_4r_widen.ll create mode 100644 test/CodeGen/Mips/msa/3r_splat.ll create mode 100644 test/CodeGen/Mips/msa/3rf.ll create mode 100644 test/CodeGen/Mips/msa/3rf_4rf.ll create mode 100644 test/CodeGen/Mips/msa/3rf_4rf_q.ll create mode 100644 test/CodeGen/Mips/msa/3rf_exdo.ll create mode 100644 test/CodeGen/Mips/msa/3rf_float_int.ll create mode 100644 test/CodeGen/Mips/msa/3rf_int_float.ll create mode 100644 test/CodeGen/Mips/msa/3rf_q.ll create mode 100644 test/CodeGen/Mips/msa/arithmetic.ll create mode 100644 test/CodeGen/Mips/msa/arithmetic_float.ll create mode 100644 test/CodeGen/Mips/msa/basic_operations.ll create mode 100644 test/CodeGen/Mips/msa/basic_operations_float.ll create mode 100644 test/CodeGen/Mips/msa/bit.ll create mode 100644 test/CodeGen/Mips/msa/bitcast.ll create mode 100644 test/CodeGen/Mips/msa/bitwise.ll create mode 100644 test/CodeGen/Mips/msa/compare.ll create mode 100644 test/CodeGen/Mips/msa/compare_float.ll create mode 100644 test/CodeGen/Mips/msa/elm_copy.ll create mode 100644 test/CodeGen/Mips/msa/elm_cxcmsa.ll create mode 100644 test/CodeGen/Mips/msa/elm_insv.ll create mode 100644 test/CodeGen/Mips/msa/elm_move.ll create mode 100644 test/CodeGen/Mips/msa/elm_shift_slide.ll create mode 100644 test/CodeGen/Mips/msa/endian.ll create mode 100644 test/CodeGen/Mips/msa/frameindex.ll create mode 100644 test/CodeGen/Mips/msa/i10.ll create mode 100644 test/CodeGen/Mips/msa/i5-a.ll create mode 100644 test/CodeGen/Mips/msa/i5-b.ll create mode 100644 test/CodeGen/Mips/msa/i5-c.ll create mode 100644 test/CodeGen/Mips/msa/i5-m.ll create mode 100644 test/CodeGen/Mips/msa/i5-s.ll create mode 100644 test/CodeGen/Mips/msa/i5_ld_st.ll create mode 100644 test/CodeGen/Mips/msa/i8.ll create mode 100644 test/CodeGen/Mips/msa/inline-asm.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s1704963983.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s1935737938.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s2090927243-simplified.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s2501752154-simplified.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s2704903805.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s3861334421.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s3926023935.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s3997499501.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s449609655-simplified.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s525530439.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-s997348632.ll create mode 100644 test/CodeGen/Mips/msa/llvm-stress-sz1-s742806235.ll create mode 100644 test/CodeGen/Mips/msa/shift-dagcombine.ll create mode 100644 test/CodeGen/Mips/msa/shuffle.ll create mode 100644 test/CodeGen/Mips/msa/special.ll create mode 100644 test/CodeGen/Mips/msa/spill.ll create mode 100644 test/CodeGen/Mips/msa/vec.ll create mode 100644 test/CodeGen/Mips/msa/vecs10.ll create mode 100644 test/CodeGen/Mips/nomips16.ll create mode 100644 test/CodeGen/Mips/optimize-fp-math.ll create mode 100644 test/CodeGen/Mips/powif64_16.ll create mode 100644 test/CodeGen/Mips/sel1c.ll create mode 100644 test/CodeGen/Mips/sel2c.ll create mode 100644 test/CodeGen/Mips/setcc-se.ll create mode 100644 test/CodeGen/Mips/simplebr.ll create mode 100644 test/CodeGen/Mips/sint-fp-store_pattern.ll create mode 100644 test/CodeGen/Mips/stack-alignment.ll create mode 100644 test/CodeGen/Mips/stackcoloring.ll create mode 100644 test/CodeGen/Mips/trap.ll create mode 100644 test/CodeGen/Mips/trap1.ll create mode 100644 test/CodeGen/NVPTX/add-128bit.ll create mode 100644 test/CodeGen/NVPTX/bug17709.ll create mode 100644 test/CodeGen/NVPTX/callchain.ll create mode 100644 test/CodeGen/NVPTX/constant-vectors.ll create mode 100644 test/CodeGen/NVPTX/ctlz.ll create mode 100644 test/CodeGen/NVPTX/ctpop.ll create mode 100644 test/CodeGen/NVPTX/cttz.ll create mode 100644 test/CodeGen/NVPTX/fast-math.ll create mode 100644 test/CodeGen/NVPTX/fp-literals.ll create mode 100644 test/CodeGen/NVPTX/i1-int-to-fp.ll create mode 100644 test/CodeGen/NVPTX/i8-param.ll create mode 100644 test/CodeGen/NVPTX/implicit-def.ll create mode 100644 test/CodeGen/NVPTX/inline-asm.ll create mode 100644 test/CodeGen/NVPTX/ldu-i8.ll create mode 100644 test/CodeGen/NVPTX/ldu-reg-plus-offset.ll create mode 100644 test/CodeGen/NVPTX/load-sext-i1.ll create mode 100644 test/CodeGen/NVPTX/local-stack-frame.ll create mode 100644 test/CodeGen/NVPTX/module-inline-asm.ll create mode 100644 test/CodeGen/NVPTX/pr16278.ll create mode 100644 test/CodeGen/NVPTX/pr17529.ll create mode 100644 test/CodeGen/NVPTX/rsqrt.ll create mode 100644 test/CodeGen/NVPTX/sext-in-reg.ll create mode 100644 test/CodeGen/NVPTX/sext-params.ll create mode 100644 test/CodeGen/NVPTX/vec-param-load.ll create mode 100644 test/CodeGen/NVPTX/vec8.ll create mode 100644 test/CodeGen/NVPTX/vector-stores.ll create mode 100644 test/CodeGen/PowerPC/2013-05-15-preinc-fold.ll create mode 100644 test/CodeGen/PowerPC/2013-07-01-PHIElimBug.ll create mode 100644 test/CodeGen/PowerPC/addrfuncstr.ll create mode 100644 test/CodeGen/PowerPC/altivec-ord.ll create mode 100644 test/CodeGen/PowerPC/ashr-neg1.ll create mode 100644 test/CodeGen/PowerPC/asm-dialect.ll create mode 100644 test/CodeGen/PowerPC/bv-pres-v8i1.ll create mode 100644 test/CodeGen/PowerPC/bv-widen-undef.ll create mode 100644 test/CodeGen/PowerPC/copysignl.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-asm.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-cpsgn.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-fp64.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-i64.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-large-ec.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-le.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-lt.ll create mode 100644 test/CodeGen/PowerPC/ctrloop-ne.ll create mode 100644 test/CodeGen/PowerPC/dyn-alloca-aligned.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-GEP-coalesce.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-binary.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-br-const.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-call.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-cmp-imm.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-conversion.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-crash.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-ext.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-fold.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-indirectbr.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-load-store.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-redefinition.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-ret.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-shifter.ll create mode 100644 test/CodeGen/PowerPC/fastisel-gep-promote-before-add.ll create mode 100644 test/CodeGen/PowerPC/fcpsgn.ll create mode 100644 test/CodeGen/PowerPC/glob-comp-aa-crash.ll create mode 100644 test/CodeGen/PowerPC/hello-reloc.s create mode 100644 test/CodeGen/PowerPC/inlineasm-i64-reg.ll create mode 100644 test/CodeGen/PowerPC/isel-rc-nox0.ll create mode 100644 test/CodeGen/PowerPC/mulli64.ll create mode 100644 test/CodeGen/PowerPC/ppc32-vacopy.ll create mode 100644 test/CodeGen/PowerPC/pr16556-2.ll create mode 100644 test/CodeGen/PowerPC/pr16556.ll create mode 100644 test/CodeGen/PowerPC/pr16573.ll create mode 100644 test/CodeGen/PowerPC/pr17168.ll create mode 100644 test/CodeGen/PowerPC/pr17354.ll create mode 100644 test/CodeGen/PowerPC/reg-names.ll create mode 100644 test/CodeGen/PowerPC/reloc-align.ll create mode 100644 test/CodeGen/PowerPC/remap-crash.ll create mode 100644 test/CodeGen/PowerPC/rlwimi-and.ll create mode 100644 test/CodeGen/PowerPC/rs-undef-use.ll create mode 100644 test/CodeGen/PowerPC/set0-v8i16.ll create mode 100644 test/CodeGen/PowerPC/sj-ctr-loop.ll create mode 100644 test/CodeGen/PowerPC/stack-realign.ll create mode 100644 test/CodeGen/PowerPC/std-unal-fi.ll create mode 100644 test/CodeGen/PowerPC/sub-bv-types.ll create mode 100644 test/CodeGen/PowerPC/subsumes-pred-regs.ll delete mode 100644 test/CodeGen/PowerPC/tls-gd-obj.ll delete mode 100644 test/CodeGen/PowerPC/tls-ie-obj.ll delete mode 100644 test/CodeGen/PowerPC/tls-ld-obj.ll create mode 100644 test/CodeGen/PowerPC/unal-altivec.ll create mode 100644 test/CodeGen/PowerPC/unal-altivec2.ll create mode 100644 test/CodeGen/PowerPC/unwind-dw2-g.ll create mode 100644 test/CodeGen/PowerPC/unwind-dw2.ll create mode 100644 test/CodeGen/PowerPC/vec-abi-align.ll create mode 100644 test/CodeGen/PowerPC/vec_fmuladd.ll create mode 100644 test/CodeGen/PowerPC/zero-not-run.ll create mode 100644 test/CodeGen/R600/32-bit-local-address-space.ll create mode 100644 test/CodeGen/R600/64bit-kernel-args.ll create mode 100644 test/CodeGen/R600/add_i64.ll create mode 100644 test/CodeGen/R600/address-space.ll delete mode 100644 test/CodeGen/R600/alu-split.ll create mode 100644 test/CodeGen/R600/array-ptr-calc-i64.ll create mode 100644 test/CodeGen/R600/atomic_load_add.ll create mode 100644 test/CodeGen/R600/atomic_load_sub.ll create mode 100644 test/CodeGen/R600/big_alu.ll create mode 100644 test/CodeGen/R600/bitcast.ll create mode 100644 test/CodeGen/R600/build_vector.ll create mode 100644 test/CodeGen/R600/combine_vloads.ll create mode 100644 test/CodeGen/R600/complex-folding.ll create mode 100644 test/CodeGen/R600/dot4-folding.ll create mode 100644 test/CodeGen/R600/extload.ll create mode 100644 test/CodeGen/R600/fadd64.ll create mode 100644 test/CodeGen/R600/fcmp64.ll create mode 100644 test/CodeGen/R600/fconst64.ll create mode 100644 test/CodeGen/R600/fdiv64.ll create mode 100644 test/CodeGen/R600/fetch-limits.r600.ll create mode 100644 test/CodeGen/R600/fetch-limits.r700+.ll create mode 100644 test/CodeGen/R600/fma.ll delete mode 100644 test/CodeGen/R600/fmul.v4f32.ll create mode 100644 test/CodeGen/R600/fmul64.ll create mode 100644 test/CodeGen/R600/fmuladd.ll create mode 100644 test/CodeGen/R600/fneg.ll create mode 100644 test/CodeGen/R600/fp64_to_sint.ll create mode 100644 test/CodeGen/R600/fpext.ll create mode 100644 test/CodeGen/R600/fptrunc.ll create mode 100644 test/CodeGen/R600/fsqrt.ll create mode 100644 test/CodeGen/R600/fsub64.ll create mode 100644 test/CodeGen/R600/gep-address-space.ll create mode 100644 test/CodeGen/R600/indirect-addressing-si.ll create mode 100644 test/CodeGen/R600/insert_vector_elt.ll create mode 100644 test/CodeGen/R600/kernel-args.ll create mode 100644 test/CodeGen/R600/lds-output-queue.ll create mode 100644 test/CodeGen/R600/lds-size.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.barrier.local.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.cube.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.imax.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.imin.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.umax.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.umin.ll create mode 100644 test/CodeGen/R600/llvm.SI.imageload.ll create mode 100644 test/CodeGen/R600/llvm.SI.resinfo.ll create mode 100644 test/CodeGen/R600/llvm.SI.sample-masked.ll create mode 100644 test/CodeGen/R600/llvm.SI.sampled.ll create mode 100644 test/CodeGen/R600/llvm.SI.tbuffer.store.ll create mode 100644 test/CodeGen/R600/llvm.SI.tid.ll create mode 100644 test/CodeGen/R600/llvm.floor.ll create mode 100644 test/CodeGen/R600/llvm.rint.ll create mode 100644 test/CodeGen/R600/llvm.round.ll create mode 100644 test/CodeGen/R600/llvm.sqrt.ll create mode 100644 test/CodeGen/R600/load-input-fold.ll create mode 100644 test/CodeGen/R600/load.vec.ll create mode 100644 test/CodeGen/R600/load64.ll create mode 100644 test/CodeGen/R600/local-memory-two-objects.ll create mode 100644 test/CodeGen/R600/local-memory.ll create mode 100644 test/CodeGen/R600/mad_int24.ll create mode 100644 test/CodeGen/R600/mad_uint24.ll create mode 100644 test/CodeGen/R600/max-literals.ll create mode 100644 test/CodeGen/R600/mul_int24.ll create mode 100644 test/CodeGen/R600/mul_uint24.ll create mode 100644 test/CodeGen/R600/packetizer.ll create mode 100644 test/CodeGen/R600/parallelandifcollapse.ll create mode 100644 test/CodeGen/R600/parallelorifcollapse.ll create mode 100644 test/CodeGen/R600/predicate-dp4.ll create mode 100644 test/CodeGen/R600/private-memory.ll create mode 100644 test/CodeGen/R600/pv-packing.ll create mode 100644 test/CodeGen/R600/r600-export-fix.ll create mode 100644 test/CodeGen/R600/r600cfg.ll create mode 100644 test/CodeGen/R600/rotr.ll create mode 100644 test/CodeGen/R600/rv7x0_count3.ll create mode 100644 test/CodeGen/R600/select.ll create mode 100644 test/CodeGen/R600/setcc64.ll create mode 100644 test/CodeGen/R600/sgpr-copy-duplicate-operand.ll create mode 100644 test/CodeGen/R600/sgpr-copy.ll create mode 100644 test/CodeGen/R600/shared-op-cycle.ll delete mode 100644 test/CodeGen/R600/short-args.ll create mode 100644 test/CodeGen/R600/si-annotate-cf-assertion.ll create mode 100644 test/CodeGen/R600/si-lod-bias.ll create mode 100644 test/CodeGen/R600/si-sgpr-spill.ll create mode 100644 test/CodeGen/R600/si-vector-hang.ll create mode 100644 test/CodeGen/R600/sign_extend.ll create mode 100644 test/CodeGen/R600/sint_to_fp64.ll create mode 100644 test/CodeGen/R600/store-vector-ptrs.ll create mode 100644 test/CodeGen/R600/structurize.ll create mode 100644 test/CodeGen/R600/structurize1.ll create mode 100644 test/CodeGen/R600/swizzle-export.ll create mode 100644 test/CodeGen/R600/tex-clause-antidep.ll create mode 100644 test/CodeGen/R600/texture-input-merge.ll create mode 100644 test/CodeGen/R600/trunc-vector-store-assertion-failure.ll create mode 100644 test/CodeGen/R600/trunc.ll create mode 100644 test/CodeGen/R600/unaligned-load-store.ll create mode 100644 test/CodeGen/R600/vertex-fetch-encoding.ll create mode 100644 test/CodeGen/R600/vselect64.ll create mode 100644 test/CodeGen/R600/vtx-schedule.ll create mode 100644 test/CodeGen/R600/wait.ll create mode 100644 test/CodeGen/R600/work-item-intrinsics.ll create mode 100644 test/CodeGen/R600/wrong-transalu-pos-fix.ll create mode 100644 test/CodeGen/R600/zero_extend.ll delete mode 100644 test/CodeGen/SI/sanity.ll create mode 100644 test/CodeGen/SPARC/2013-05-17-CallFrame.ll create mode 100644 test/CodeGen/SPARC/blockaddr.ll create mode 100644 test/CodeGen/SPARC/exception.ll create mode 100644 test/CodeGen/SPARC/float.ll create mode 100644 test/CodeGen/SPARC/fp128.ll create mode 100644 test/CodeGen/SPARC/leafproc.ll create mode 100644 test/CodeGen/SPARC/rem.ll create mode 100644 test/CodeGen/SPARC/setjmp.ll create mode 100644 test/CodeGen/SPARC/tls.ll create mode 100644 test/CodeGen/SystemZ/Large/branch-range-01.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-02.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-03.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-04.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-05.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-06.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-07.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-08.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-09.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-10.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-11.py create mode 100644 test/CodeGen/SystemZ/Large/branch-range-12.py create mode 100644 test/CodeGen/SystemZ/Large/lit.local.cfg create mode 100644 test/CodeGen/SystemZ/Large/spill-01.py create mode 100644 test/CodeGen/SystemZ/Large/spill-02.py create mode 100644 test/CodeGen/SystemZ/alias-01.ll create mode 100644 test/CodeGen/SystemZ/and-07.ll create mode 100644 test/CodeGen/SystemZ/and-08.ll create mode 100644 test/CodeGen/SystemZ/asm-17.ll create mode 100644 test/CodeGen/SystemZ/asm-18.ll create mode 100644 test/CodeGen/SystemZ/branch-06.ll create mode 100644 test/CodeGen/SystemZ/branch-07.ll create mode 100644 test/CodeGen/SystemZ/branch-08.ll create mode 100644 test/CodeGen/SystemZ/branch-09.ll create mode 100644 test/CodeGen/SystemZ/branch-10.ll create mode 100644 test/CodeGen/SystemZ/call-03.ll create mode 100644 test/CodeGen/SystemZ/cond-load-01.ll create mode 100644 test/CodeGen/SystemZ/cond-load-02.ll create mode 100644 test/CodeGen/SystemZ/cond-move-01.ll create mode 100644 test/CodeGen/SystemZ/cond-store-01.ll create mode 100644 test/CodeGen/SystemZ/cond-store-02.ll create mode 100644 test/CodeGen/SystemZ/cond-store-03.ll create mode 100644 test/CodeGen/SystemZ/cond-store-04.ll create mode 100644 test/CodeGen/SystemZ/cond-store-05.ll create mode 100644 test/CodeGen/SystemZ/cond-store-06.ll create mode 100644 test/CodeGen/SystemZ/cond-store-07.ll create mode 100644 test/CodeGen/SystemZ/cond-store-08.ll create mode 100644 test/CodeGen/SystemZ/fp-cmp-04.ll create mode 100644 test/CodeGen/SystemZ/fp-move-09.ll create mode 100644 test/CodeGen/SystemZ/fp-round-02.ll create mode 100644 test/CodeGen/SystemZ/int-abs-01.ll create mode 100644 test/CodeGen/SystemZ/int-add-13.ll create mode 100644 test/CodeGen/SystemZ/int-add-14.ll create mode 100644 test/CodeGen/SystemZ/int-add-15.ll create mode 100644 test/CodeGen/SystemZ/int-add-16.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-44.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-45.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-46.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-47.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-48.ll create mode 100644 test/CodeGen/SystemZ/int-cmp-49.ll create mode 100644 test/CodeGen/SystemZ/int-conv-11.ll create mode 100644 test/CodeGen/SystemZ/int-div-06.ll create mode 100644 test/CodeGen/SystemZ/int-neg-02.ll create mode 100644 test/CodeGen/SystemZ/int-sub-07.ll create mode 100644 test/CodeGen/SystemZ/int-sub-08.ll create mode 100644 test/CodeGen/SystemZ/int-sub-09.ll create mode 100644 test/CodeGen/SystemZ/loop-01.ll create mode 100644 test/CodeGen/SystemZ/memchr-01.ll create mode 100644 test/CodeGen/SystemZ/memchr-02.ll create mode 100644 test/CodeGen/SystemZ/memcmp-01.ll create mode 100644 test/CodeGen/SystemZ/memcmp-02.ll create mode 100644 test/CodeGen/SystemZ/memcpy-01.ll create mode 100644 test/CodeGen/SystemZ/memcpy-02.ll create mode 100644 test/CodeGen/SystemZ/memset-01.ll create mode 100644 test/CodeGen/SystemZ/memset-02.ll create mode 100644 test/CodeGen/SystemZ/memset-03.ll create mode 100644 test/CodeGen/SystemZ/memset-04.ll create mode 100644 test/CodeGen/SystemZ/or-07.ll create mode 100644 test/CodeGen/SystemZ/or-08.ll create mode 100644 test/CodeGen/SystemZ/prefetch-01.ll create mode 100644 test/CodeGen/SystemZ/risbg-01.ll create mode 100644 test/CodeGen/SystemZ/risbg-02.ll create mode 100644 test/CodeGen/SystemZ/rnsbg-01.ll create mode 100644 test/CodeGen/SystemZ/rosbg-01.ll create mode 100644 test/CodeGen/SystemZ/rxsbg-01.ll create mode 100644 test/CodeGen/SystemZ/setcc-01.ll create mode 100644 test/CodeGen/SystemZ/setcc-02.ll create mode 100644 test/CodeGen/SystemZ/shift-09.ll create mode 100644 test/CodeGen/SystemZ/shift-10.ll create mode 100644 test/CodeGen/SystemZ/spill-01.ll create mode 100644 test/CodeGen/SystemZ/strcmp-01.ll create mode 100644 test/CodeGen/SystemZ/strcmp-02.ll create mode 100644 test/CodeGen/SystemZ/strcpy-01.ll create mode 100644 test/CodeGen/SystemZ/strlen-01.ll create mode 100644 test/CodeGen/SystemZ/strlen-02.ll create mode 100644 test/CodeGen/SystemZ/unaligned-01.ll create mode 100644 test/CodeGen/SystemZ/xor-07.ll create mode 100644 test/CodeGen/SystemZ/xor-08.ll create mode 100644 test/CodeGen/Thumb/PR17309.ll create mode 100644 test/CodeGen/Thumb2/tail-call-r9.ll create mode 100644 test/CodeGen/Thumb2/v8_IT_1.ll create mode 100644 test/CodeGen/Thumb2/v8_IT_2.ll create mode 100644 test/CodeGen/Thumb2/v8_IT_3.ll create mode 100644 test/CodeGen/Thumb2/v8_IT_4.ll create mode 100644 test/CodeGen/Thumb2/v8_IT_5.ll delete mode 100644 test/CodeGen/X86/2007-05-07-InvokeSRet.ll delete mode 100644 test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll delete mode 100644 test/CodeGen/X86/2012-02-20-MachineCPBug.ll create mode 100644 test/CodeGen/X86/2013-10-14-FastISel-incorrect-vreg.ll create mode 100644 test/CodeGen/X86/GC/ocaml-gc-assert.ll create mode 100644 test/CodeGen/X86/aes_intrinsics.ll create mode 100644 test/CodeGen/X86/alias-error.ll create mode 100644 test/CodeGen/X86/anyregcc-crash.ll create mode 100644 test/CodeGen/X86/anyregcc.ll create mode 100644 test/CodeGen/X86/atom-lea-addw-bug.ll create mode 100644 test/CodeGen/X86/avx2-gather.ll create mode 100644 test/CodeGen/X86/avx2-vector-shifts.ll create mode 100644 test/CodeGen/X86/avx512-arith.ll create mode 100644 test/CodeGen/X86/avx512-build-vector.ll create mode 100644 test/CodeGen/X86/avx512-cmp.ll create mode 100644 test/CodeGen/X86/avx512-cvt.ll create mode 100644 test/CodeGen/X86/avx512-fma-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512-fma.ll create mode 100644 test/CodeGen/X86/avx512-gather-scatter-intrin.ll create mode 100644 test/CodeGen/X86/avx512-insert-extract.ll create mode 100644 test/CodeGen/X86/avx512-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512-mask-op.ll create mode 100644 test/CodeGen/X86/avx512-mov.ll create mode 100644 test/CodeGen/X86/avx512-select.ll create mode 100644 test/CodeGen/X86/avx512-shift.ll create mode 100644 test/CodeGen/X86/avx512-shuffle.ll create mode 100644 test/CodeGen/X86/avx512-trunc-ext.ll create mode 100644 test/CodeGen/X86/avx512-vbroadcast.ll create mode 100644 test/CodeGen/X86/avx512-vec-cmp.ll create mode 100644 test/CodeGen/X86/break-avx-dep.ll create mode 100644 test/CodeGen/X86/chain_order.ll create mode 100644 test/CodeGen/X86/coff-feat00.ll create mode 100644 test/CodeGen/X86/dagcombine-shifts.ll create mode 100644 test/CodeGen/X86/dagcombine-unsafe-math.ll delete mode 100644 test/CodeGen/X86/dagcombine_unsafe_math.ll delete mode 100644 test/CodeGen/X86/dbg-at-specficiation.ll delete mode 100644 test/CodeGen/X86/dbg-byval-parameter.ll delete mode 100644 test/CodeGen/X86/dbg-const-int.ll delete mode 100644 test/CodeGen/X86/dbg-const.ll delete mode 100644 test/CodeGen/X86/dbg-declare-arg.ll delete mode 100644 test/CodeGen/X86/dbg-declare.ll delete mode 100644 test/CodeGen/X86/dbg-file-name.ll delete mode 100644 test/CodeGen/X86/dbg-i128-const.ll delete mode 100644 test/CodeGen/X86/dbg-large-unsigned-const.ll delete mode 100644 test/CodeGen/X86/dbg-merge-loc-entry.ll delete mode 100644 test/CodeGen/X86/dbg-prolog-end.ll delete mode 100644 test/CodeGen/X86/dbg-subrange.ll delete mode 100644 test/CodeGen/X86/dbg-value-dag-combine.ll delete mode 100644 test/CodeGen/X86/dbg-value-isel.ll delete mode 100644 test/CodeGen/X86/dbg-value-location.ll delete mode 100644 test/CodeGen/X86/dbg-value-range.ll create mode 100644 test/CodeGen/X86/dyn_alloca_aligned.ll create mode 100644 test/CodeGen/X86/emit-big-cst.ll create mode 100644 test/CodeGen/X86/extended-fma-contraction.ll create mode 100644 test/CodeGen/X86/fast-isel-store.ll delete mode 100644 test/CodeGen/X86/fast-isel-unaligned-store.ll create mode 100644 test/CodeGen/X86/fastisel-gep-promote-before-add.ll create mode 100644 test/CodeGen/X86/floor-soft-float.ll create mode 100644 test/CodeGen/X86/fma_patterns_wide.ll create mode 100644 test/CodeGen/X86/fp-select-cmp-and.ll create mode 100644 test/CodeGen/X86/fp-une-cmp.ll create mode 100644 test/CodeGen/X86/frame-base.ll create mode 100644 test/CodeGen/X86/i486-fence-loop.ll create mode 100644 test/CodeGen/X86/ident-metadata.ll create mode 100644 test/CodeGen/X86/isel-optnone.ll create mode 100644 test/CodeGen/X86/large-gep-chain.ll create mode 100644 test/CodeGen/X86/load-slice.ll create mode 100644 test/CodeGen/X86/long-extend.ll create mode 100644 test/CodeGen/X86/merge_store.ll create mode 100644 test/CodeGen/X86/misched-fusion.ll create mode 100644 test/CodeGen/X86/newline-and-quote.ll create mode 100644 test/CodeGen/X86/no-elf-compact-unwind.ll create mode 100644 test/CodeGen/X86/nocx16.ll create mode 100644 test/CodeGen/X86/nonconst-static-ev.ll create mode 100644 test/CodeGen/X86/nonconst-static-iv.ll create mode 100644 test/CodeGen/X86/patchpoint.ll create mode 100644 test/CodeGen/X86/peep-test-4.ll create mode 100644 test/CodeGen/X86/pr16031.ll create mode 100644 test/CodeGen/X86/pr16360.ll create mode 100644 test/CodeGen/X86/pr16807.ll create mode 100644 test/CodeGen/X86/pr17546.ll create mode 100644 test/CodeGen/X86/pr17631.ll create mode 100644 test/CodeGen/X86/pr17764.ll create mode 100644 test/CodeGen/X86/pr18014.ll create mode 100644 test/CodeGen/X86/pr18023.ll create mode 100644 test/CodeGen/X86/pr18054.ll create mode 100644 test/CodeGen/X86/pr18162.ll create mode 100644 test/CodeGen/X86/prefixdata.ll delete mode 100644 test/CodeGen/X86/rem-2.ll create mode 100644 test/CodeGen/X86/remat-phys-dead.ll create mode 100644 test/CodeGen/X86/returned-trunc-tail-calls.ll create mode 100644 test/CodeGen/X86/setcc-narrowing.ll create mode 100644 test/CodeGen/X86/setcc-sentinals.ll create mode 100644 test/CodeGen/X86/sha.ll create mode 100644 test/CodeGen/X86/sibcall-6.ll create mode 100644 test/CodeGen/X86/simple-zext.ll create mode 100644 test/CodeGen/X86/sqrt-fastmath.ll create mode 100644 test/CodeGen/X86/sse-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/sse2-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/sse2-vector-shifts.ll create mode 100644 test/CodeGen/X86/sse3-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/sse41-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/sse42-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/ssse3-intrinsics-x86.ll create mode 100644 test/CodeGen/X86/stack-protector-dbginfo.ll create mode 100644 test/CodeGen/X86/stack-protector-vreg-to-vreg-copy.ll create mode 100644 test/CodeGen/X86/stackmap.ll delete mode 100644 test/CodeGen/X86/subtarget-feature-change.ll create mode 100644 test/CodeGen/X86/tail-call-attrs.ll create mode 100644 test/CodeGen/X86/tail-call-legality.ll create mode 100644 test/CodeGen/X86/tailcall-calleesave.ll create mode 100644 test/CodeGen/X86/tbm-intrinsics-x86_64.ll create mode 100644 test/CodeGen/X86/tbm_patterns.ll create mode 100644 test/CodeGen/X86/tlv-3.ll create mode 100644 test/CodeGen/X86/unaligned-spill-folding.ll create mode 100644 test/CodeGen/X86/unwind-init.ll create mode 100644 test/CodeGen/X86/v4i32load-crash.ll create mode 100644 test/CodeGen/X86/vec_round.ll create mode 100644 test/CodeGen/X86/vec_setcc.ll create mode 100644 test/CodeGen/X86/vec_split.ll create mode 100644 test/CodeGen/X86/warn-stack.ll create mode 100644 test/CodeGen/X86/weak_def_can_be_hidden.ll create mode 100644 test/CodeGen/X86/x86-64-psub.ll delete mode 100644 test/CodeGen/XCore/2011-08-01-VarargsBug.ll create mode 100644 test/CodeGen/XCore/alignment.ll create mode 100644 test/CodeGen/XCore/atomic.ll create mode 100644 test/CodeGen/XCore/byVal.ll create mode 100644 test/CodeGen/XCore/epilogue_prologue.ll create mode 100644 test/CodeGen/XCore/exception.ll create mode 100644 test/CodeGen/XCore/inline-asm.ll create mode 100644 test/CodeGen/XCore/linkage.ll create mode 100644 test/CodeGen/XCore/shedulingPreference.ll create mode 100644 test/CodeGen/XCore/varargs.ll create mode 100644 test/CodeGen/XCore/zext.ll create mode 100644 test/CodeGen/XCore/zextfree.ll create mode 100644 test/DebugInfo/ARM/PR16736.ll create mode 100644 test/DebugInfo/ARM/lit.local.cfg create mode 100644 test/DebugInfo/ARM/lowerbdgdeclare_vla.ll create mode 100644 test/DebugInfo/ARM/selectiondag-deadcode.ll create mode 100755 test/DebugInfo/Inputs/dwarfdump-inl-test.high_pc.elf-x86-64 create mode 100644 test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp create mode 100644 test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o create mode 100755 test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64.debuglink create mode 100644 test/DebugInfo/Inputs/dwarfdump-type-units.cc create mode 100644 test/DebugInfo/Inputs/dwarfdump-type-units.elf-x86-64 delete mode 100644 test/DebugInfo/Inputs/lit.local.cfg create mode 100755 test/DebugInfo/Inputs/macho-universal create mode 100644 test/DebugInfo/Inputs/macho-universal.cc create mode 100644 test/DebugInfo/PowerPC/lit.local.cfg create mode 100644 test/DebugInfo/PowerPC/tls-fission.ll create mode 100644 test/DebugInfo/PowerPC/tls.ll create mode 100644 test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll create mode 100644 test/DebugInfo/X86/arguments.ll create mode 100644 test/DebugInfo/X86/byvalstruct.ll create mode 100644 test/DebugInfo/X86/coff_relative_names.ll create mode 100644 test/DebugInfo/X86/data_member_location.ll create mode 100644 test/DebugInfo/X86/dbg-at-specficiation.ll create mode 100644 test/DebugInfo/X86/dbg-byval-parameter.ll create mode 100644 test/DebugInfo/X86/dbg-const-int.ll create mode 100644 test/DebugInfo/X86/dbg-const.ll create mode 100644 test/DebugInfo/X86/dbg-declare-arg.ll create mode 100644 test/DebugInfo/X86/dbg-declare.ll create mode 100644 test/DebugInfo/X86/dbg-file-name.ll create mode 100644 test/DebugInfo/X86/dbg-i128-const.ll create mode 100644 test/DebugInfo/X86/dbg-large-unsigned-const.ll create mode 100644 test/DebugInfo/X86/dbg-merge-loc-entry.ll create mode 100644 test/DebugInfo/X86/dbg-prolog-end.ll create mode 100644 test/DebugInfo/X86/dbg-subrange.ll create mode 100644 test/DebugInfo/X86/dbg-value-dag-combine.ll create mode 100644 test/DebugInfo/X86/dbg-value-isel.ll create mode 100644 test/DebugInfo/X86/dbg-value-location.ll create mode 100644 test/DebugInfo/X86/dbg-value-range.ll create mode 100644 test/DebugInfo/X86/dbg-value-terminator.ll create mode 100644 test/DebugInfo/X86/dbg_value_direct.ll create mode 100644 test/DebugInfo/X86/dwarf-aranges-no-dwarf-labels.ll create mode 100644 test/DebugInfo/X86/dwarf-aranges.ll create mode 100644 test/DebugInfo/X86/dwarf-public-names.ll create mode 100644 test/DebugInfo/X86/dwarf-pubnames-split.ll create mode 100644 test/DebugInfo/X86/fission-hash.ll create mode 100644 test/DebugInfo/X86/fission-ranges.ll create mode 100644 test/DebugInfo/X86/generate-odr-hash.ll create mode 100644 test/DebugInfo/X86/gnu-public-names-empty.ll create mode 100644 test/DebugInfo/X86/gnu-public-names.ll create mode 100644 test/DebugInfo/X86/multiple-aranges.ll create mode 100644 test/DebugInfo/X86/parameters.ll create mode 100644 test/DebugInfo/X86/ref_addr_relocation.ll create mode 100644 test/DebugInfo/X86/reference-argument.ll create mode 100644 test/DebugInfo/X86/template.ll create mode 100644 test/DebugInfo/X86/tls-fission.ll create mode 100644 test/DebugInfo/X86/tls.ll create mode 100644 test/DebugInfo/X86/vla.ll create mode 100644 test/DebugInfo/debuginfofinder-multiple-cu.ll create mode 100644 test/DebugInfo/dwarfdump-debug-loc-simple.test create mode 100644 test/DebugInfo/dwarfdump-type-units.test create mode 100644 test/DebugInfo/enum.ll create mode 100644 test/DebugInfo/global.ll create mode 100644 test/DebugInfo/inlined-arguments.ll delete mode 100644 test/DebugInfo/lit.local.cfg create mode 100644 test/DebugInfo/member-order.ll create mode 100644 test/DebugInfo/template-recursive-void.ll create mode 100644 test/DebugInfo/tu-composite.ll create mode 100644 test/DebugInfo/tu-member-pointer.ll create mode 100644 test/DebugInfo/version.ll create mode 100644 test/ExecutionEngine/MCJIT/Inputs/cross-module-b.ll create mode 100644 test/ExecutionEngine/MCJIT/Inputs/multi-module-b.ll create mode 100644 test/ExecutionEngine/MCJIT/Inputs/multi-module-c.ll create mode 100644 test/ExecutionEngine/MCJIT/Inputs/multi-module-eh-b.ll create mode 100644 test/ExecutionEngine/MCJIT/cross-module-a.ll create mode 100644 test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/MCJIT/eh-lg-pic.ll create mode 100644 test/ExecutionEngine/MCJIT/eh-sm-pic.ll create mode 100644 test/ExecutionEngine/MCJIT/hello-sm-pic.ll create mode 100644 test/ExecutionEngine/MCJIT/multi-module-a.ll create mode 100644 test/ExecutionEngine/MCJIT/multi-module-eh-a.ll create mode 100644 test/ExecutionEngine/MCJIT/multi-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/Inputs/cross-module-b.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/Inputs/multi-module-b.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/Inputs/multi-module-c.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/cross-module-a.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/cross-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/lit.local.cfg create mode 100644 test/ExecutionEngine/MCJIT/remote/multi-module-a.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/multi-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/stubs-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/stubs-sm-pic.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-data-align-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-sm-pic.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-sm-pic.ll delete mode 100644 test/ExecutionEngine/MCJIT/simpletest-remote.ll delete mode 100644 test/ExecutionEngine/MCJIT/stubs-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/stubs-sm-pic.ll delete mode 100644 test/ExecutionEngine/MCJIT/test-common-symbols-remote.ll delete mode 100644 test/ExecutionEngine/MCJIT/test-data-align-remote.ll delete mode 100644 test/ExecutionEngine/MCJIT/test-fp-no-external-funcs-remote.ll delete mode 100644 test/ExecutionEngine/MCJIT/test-global-init-nonzero-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/test-global-init-nonzero-sm-pic.ll delete mode 100644 test/ExecutionEngine/MCJIT/test-ptr-reloc-remote.ll create mode 100644 test/ExecutionEngine/MCJIT/test-ptr-reloc-sm-pic.ll create mode 100644 test/ExecutionEngine/RuntimeDyld/Inputs/arm_secdiff_reloc.o create mode 100644 test/ExecutionEngine/RuntimeDyld/arm_secdiff_reloc.test create mode 100644 test/ExecutionEngine/fma3-jit.ll create mode 100644 test/ExecutionEngine/mov64zext32.ll create mode 100644 test/ExecutionEngine/test-interp-vec-cast.ll create mode 100644 test/ExecutionEngine/test-interp-vec-insertelement.ll create mode 100644 test/ExecutionEngine/test-interp-vec-insertextractvalue.ll create mode 100644 test/ExecutionEngine/test-interp-vec-select.ll create mode 100644 test/ExecutionEngine/test-interp-vec-shift.ll create mode 100644 test/ExecutionEngine/test-interp-vec-shuffle.ll create mode 100644 test/Feature/cold.ll delete mode 100644 test/Feature/lit.local.cfg create mode 100644 test/Feature/optnone.ll create mode 100644 test/Feature/prefixdata.ll create mode 100644 test/FileCheck/check-a-b-has-b.txt create mode 100644 test/FileCheck/check-b-a-has-b.txt create mode 100644 test/FileCheck/check-dag-multi-prefix-2.txt create mode 100644 test/FileCheck/check-dag-multi-prefix.txt create mode 100644 test/FileCheck/check-dag-substring-prefix.txt create mode 100644 test/FileCheck/check-dag-xfails.txt create mode 100644 test/FileCheck/check-dag.txt create mode 100644 test/FileCheck/check-label-dag-capture.txt create mode 100644 test/FileCheck/check-label-dag.txt create mode 100644 test/FileCheck/check-label.txt create mode 100644 test/FileCheck/check-multi-prefix-label.txt create mode 100644 test/FileCheck/check-multiple-prefixes-mixed.txt create mode 100644 test/FileCheck/check-multiple-prefixes-nomatch.txt create mode 100644 test/FileCheck/check-multiple-prefixes-substr.txt create mode 100644 test/FileCheck/check-prefixes.txt create mode 100644 test/FileCheck/check-substring-multi-prefix-2.txt create mode 100644 test/FileCheck/check-substring-multi-prefix.txt create mode 100644 test/FileCheck/first-character-match.txt create mode 100644 test/FileCheck/line-count-2.txt create mode 100644 test/FileCheck/line-count.txt delete mode 100644 test/FileCheck/lit.local.cfg create mode 100644 test/FileCheck/multiple-missing-prefixes.txt create mode 100644 test/FileCheck/separate-multi-prefix.txt create mode 100644 test/FileCheck/validate-check-prefix.txt create mode 100644 test/Instrumentation/AddressSanitizer/coverage.ll create mode 100644 test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll create mode 100644 test/Instrumentation/AddressSanitizer/lifetime-uar.ll delete mode 100644 test/Instrumentation/AddressSanitizer/lit.local.cfg delete mode 100644 test/Instrumentation/BoundsChecking/lit.local.cfg create mode 100644 test/Instrumentation/BoundsChecking/simple-32.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/Inputs/abilist.txt create mode 100644 test/Instrumentation/DataFlowSanitizer/abilist.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/args-unreachable-bb.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/arith.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/call.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/debug-nonzero-labels.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/load.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/memset.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/prefix-rename.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/store.ll create mode 100644 test/Instrumentation/MemorySanitizer/X86/vararg.ll create mode 100644 test/Instrumentation/MemorySanitizer/atomics.ll delete mode 100644 test/Instrumentation/MemorySanitizer/lit.local.cfg create mode 100644 test/Instrumentation/MemorySanitizer/return_from_main.ll create mode 100644 test/Instrumentation/MemorySanitizer/vector_cvt.ll create mode 100644 test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll delete mode 100644 test/Instrumentation/ThreadSanitizer/lit.local.cfg create mode 100644 test/Instrumentation/ThreadSanitizer/no_sanitize_thread.ll delete mode 100644 test/Integer/lit.local.cfg create mode 100644 test/LTO/cfi_endproc.ll create mode 100644 test/LTO/linkonce_odr_func.ll create mode 100644 test/LTO/lit.local.cfg create mode 100644 test/LTO/runtime-library.ll create mode 100644 test/Linker/Inputs/type-unique-inheritance-a.ll create mode 100644 test/Linker/Inputs/type-unique-inheritance-b.ll create mode 100644 test/Linker/Inputs/type-unique-simple2-a.ll create mode 100644 test/Linker/Inputs/type-unique-simple2-b.ll delete mode 100644 test/Linker/lit.local.cfg create mode 100644 test/Linker/prefixdata.ll create mode 100644 test/Linker/transitive-lazy-link.ll create mode 100644 test/Linker/type-unique-inheritance.ll create mode 100644 test/Linker/type-unique-simple-a.ll create mode 100644 test/Linker/type-unique-simple-b.ll create mode 100644 test/Linker/type-unique-simple2.ll create mode 100644 test/Linker/unnamed-addr-err-a.ll create mode 100644 test/Linker/unnamed-addr-err-b.ll create mode 100644 test/MC/AArch64/adrp-relocation.s create mode 100644 test/MC/AArch64/basic-pic.s create mode 100644 test/MC/AArch64/elf-extern.s create mode 100644 test/MC/AArch64/elf-reloc-addend.s create mode 100644 test/MC/AArch64/inline-asm-modifiers.s create mode 100644 test/MC/AArch64/jump-table.s create mode 100644 test/MC/AArch64/neon-2velem.s create mode 100644 test/MC/AArch64/neon-3vdiff.s create mode 100644 test/MC/AArch64/neon-aba-abd.s create mode 100644 test/MC/AArch64/neon-across.s create mode 100644 test/MC/AArch64/neon-add-pairwise.s create mode 100644 test/MC/AArch64/neon-add-sub-instructions.s create mode 100644 test/MC/AArch64/neon-bitwise-instructions.s create mode 100644 test/MC/AArch64/neon-compare-instructions.s create mode 100644 test/MC/AArch64/neon-crypto.s create mode 100644 test/MC/AArch64/neon-diagnostics.s create mode 100644 test/MC/AArch64/neon-extract.s create mode 100644 test/MC/AArch64/neon-facge-facgt.s create mode 100644 test/MC/AArch64/neon-frsqrt-frecp.s create mode 100644 test/MC/AArch64/neon-halving-add-sub.s create mode 100644 test/MC/AArch64/neon-max-min-pairwise.s create mode 100644 test/MC/AArch64/neon-max-min.s create mode 100644 test/MC/AArch64/neon-mla-mls-instructions.s create mode 100644 test/MC/AArch64/neon-mov.s create mode 100644 test/MC/AArch64/neon-mul-div-instructions.s create mode 100644 test/MC/AArch64/neon-perm.s create mode 100644 test/MC/AArch64/neon-rounding-halving-add.s create mode 100644 test/MC/AArch64/neon-rounding-shift.s create mode 100644 test/MC/AArch64/neon-saturating-add-sub.s create mode 100644 test/MC/AArch64/neon-saturating-rounding-shift.s create mode 100644 test/MC/AArch64/neon-saturating-shift.s create mode 100644 test/MC/AArch64/neon-scalar-abs.s create mode 100644 test/MC/AArch64/neon-scalar-add-sub.s create mode 100644 test/MC/AArch64/neon-scalar-by-elem-mla.s create mode 100644 test/MC/AArch64/neon-scalar-by-elem-mul.s create mode 100644 test/MC/AArch64/neon-scalar-by-elem-saturating-mla.s create mode 100644 test/MC/AArch64/neon-scalar-by-elem-saturating-mul.s create mode 100644 test/MC/AArch64/neon-scalar-compare.s create mode 100644 test/MC/AArch64/neon-scalar-cvt.s create mode 100644 test/MC/AArch64/neon-scalar-dup.s create mode 100644 test/MC/AArch64/neon-scalar-extract-narrow.s create mode 100644 test/MC/AArch64/neon-scalar-fp-compare.s create mode 100644 test/MC/AArch64/neon-scalar-mul.s create mode 100644 test/MC/AArch64/neon-scalar-neg.s create mode 100644 test/MC/AArch64/neon-scalar-recip.s create mode 100644 test/MC/AArch64/neon-scalar-reduce-pairwise.s create mode 100644 test/MC/AArch64/neon-scalar-rounding-shift.s create mode 100644 test/MC/AArch64/neon-scalar-saturating-add-sub.s create mode 100644 test/MC/AArch64/neon-scalar-saturating-rounding-shift.s create mode 100644 test/MC/AArch64/neon-scalar-saturating-shift.s create mode 100644 test/MC/AArch64/neon-scalar-shift-imm.s create mode 100644 test/MC/AArch64/neon-scalar-shift.s create mode 100644 test/MC/AArch64/neon-shift-left-long.s create mode 100644 test/MC/AArch64/neon-shift.s create mode 100644 test/MC/AArch64/neon-simd-copy.s create mode 100644 test/MC/AArch64/neon-simd-ldst-multi-elem.s create mode 100644 test/MC/AArch64/neon-simd-ldst-one-elem.s create mode 100644 test/MC/AArch64/neon-simd-misc.s create mode 100644 test/MC/AArch64/neon-simd-post-ldst-multi-elem.s create mode 100644 test/MC/AArch64/neon-simd-shift.s create mode 100644 test/MC/AArch64/neon-tbl.s create mode 100644 test/MC/AArch64/noneon-diagnostics.s create mode 100644 test/MC/ARM/2010-11-30-reloc-movt.s create mode 100644 test/MC/ARM/align_arm_2_thumb.s create mode 100644 test/MC/ARM/align_thumb_2_arm.s create mode 100644 test/MC/ARM/arm-ldrd.s create mode 100644 test/MC/ARM/arm-thumb-cpus-default.s create mode 100644 test/MC/ARM/arm-thumb-cpus.s create mode 100644 test/MC/ARM/basic-arm-instructions-v8.s create mode 100644 test/MC/ARM/basic-thumb2-instructions-v8.s create mode 100644 test/MC/ARM/crc32-thumb.s create mode 100644 test/MC/ARM/crc32.s create mode 100644 test/MC/ARM/deprecated-v8.s create mode 100644 test/MC/ARM/diagnostics-noneon.s create mode 100644 test/MC/ARM/directive-cpu.s create mode 100644 test/MC/ARM/directive-eabi_attribute.s create mode 100644 test/MC/ARM/directive-fpu-multiple.s create mode 100644 test/MC/ARM/directive-fpu.s create mode 100644 test/MC/ARM/eh-compact-pr0.s create mode 100644 test/MC/ARM/eh-compact-pr1.s create mode 100644 test/MC/ARM/eh-directive-cantunwind-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-cantunwind.s create mode 100644 test/MC/ARM/eh-directive-fnend-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-fnstart-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-handlerdata.s create mode 100644 test/MC/ARM/eh-directive-integrated-test.s create mode 100644 test/MC/ARM/eh-directive-multiple-offsets.s create mode 100644 test/MC/ARM/eh-directive-pad-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-pad.s create mode 100644 test/MC/ARM/eh-directive-personality-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-personality.s create mode 100644 test/MC/ARM/eh-directive-save-diagnoatics.s create mode 100644 test/MC/ARM/eh-directive-save.s create mode 100644 test/MC/ARM/eh-directive-section-comdat.s create mode 100644 test/MC/ARM/eh-directive-section-multiple-func.s create mode 100644 test/MC/ARM/eh-directive-section.s create mode 100644 test/MC/ARM/eh-directive-setfp-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-setfp.s create mode 100644 test/MC/ARM/eh-directive-text-section-multiple-func.s create mode 100644 test/MC/ARM/eh-directive-text-section.s create mode 100644 test/MC/ARM/eh-directive-vsave-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-vsave.s delete mode 100644 test/MC/ARM/elf-eflags-eabi-cg.ll create mode 100644 test/MC/ARM/fp-armv8.s create mode 100644 test/MC/ARM/idiv.s create mode 100644 test/MC/ARM/invalid-barrier.s create mode 100644 test/MC/ARM/invalid-crc32.s create mode 100644 test/MC/ARM/invalid-fp-armv8.s create mode 100644 test/MC/ARM/invalid-idiv.s create mode 100644 test/MC/ARM/invalid-neon-v8.s create mode 100644 test/MC/ARM/load-store-acquire-release-v8-thumb.s create mode 100644 test/MC/ARM/load-store-acquire-release-v8.s create mode 100644 test/MC/ARM/neon-crypto.s create mode 100644 test/MC/ARM/neon-v8.s create mode 100644 test/MC/ARM/obsolete-v8.s create mode 100644 test/MC/ARM/single-precision-fp.s create mode 100644 test/MC/ARM/thumb-fp-armv8.s create mode 100644 test/MC/ARM/thumb-hints.s create mode 100644 test/MC/ARM/thumb-invalid-crypto.txt create mode 100644 test/MC/ARM/thumb-neon-crypto.s create mode 100644 test/MC/ARM/thumb-neon-v8.s delete mode 100644 test/MC/ARM/thumb-nop.s create mode 100644 test/MC/ARM/thumb-only-conditionals.s create mode 100644 test/MC/ARM/thumb2-branches.s create mode 100644 test/MC/ARM/thumb2-ldrd.s create mode 100644 test/MC/ARM/thumb2-pldw.s create mode 100644 test/MC/ARM/v8_IT_manual.s create mode 100644 test/MC/AsmParser/cfi-window-save.s create mode 100644 test/MC/AsmParser/secure_log_unique.s create mode 100644 test/MC/COFF/alias.s create mode 100644 test/MC/COFF/bss_section.ll create mode 100644 test/MC/COFF/eh-frame.s create mode 100644 test/MC/COFF/feat00.s create mode 100644 test/MC/COFF/linkonce-invalid.s create mode 100644 test/MC/COFF/linkonce.s create mode 100755 test/MC/COFF/lset0.s create mode 100644 test/MC/COFF/rdata.ll create mode 100644 test/MC/COFF/section-comdat.s create mode 100644 test/MC/COFF/section-invalid-flags.s create mode 100644 test/MC/COFF/section-name-encoding.s create mode 100644 test/MC/COFF/section.s create mode 100644 test/MC/COFF/seh-align1.s create mode 100644 test/MC/COFF/seh-align2.s create mode 100644 test/MC/COFF/seh-align3.s create mode 100644 test/MC/COFF/tricky-names.ll delete mode 100644 test/MC/COFF/weak-symbol-section-specification.ll create mode 100644 test/MC/COFF/weak-symbol.ll create mode 100644 test/MC/Disassembler/AArch64/neon-instructions.txt create mode 100644 test/MC/Disassembler/ARM/arm-LDREXD-reencoding.txt create mode 100644 test/MC/Disassembler/ARM/arm-STREXD-reencoding.txt create mode 100644 test/MC/Disassembler/ARM/basic-arm-instructions-v8.txt create mode 100644 test/MC/Disassembler/ARM/crc32-thumb.txt create mode 100644 test/MC/Disassembler/ARM/crc32.txt create mode 100644 test/MC/Disassembler/ARM/fp-armv8.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-BFI-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-DMB-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-DSB-arm.txt create mode 100644 test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-IT-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDM-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-LDRrs-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MCR-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MOVr-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MOVs-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MRRC2-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-MSRi-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-SBFX-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-SRS-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-SXTB-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLD1LNd32_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLD4DUPd32_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLD4LNd32_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VQADD-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VST1LNd32_UPD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VST1d8Twb_register-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-VST4LNd32_UPD-thumb.txt create mode 100644 test/MC/Disassembler/ARM/invalid-armv7.txt create mode 100644 test/MC/Disassembler/ARM/invalid-armv8.txt create mode 100644 test/MC/Disassembler/ARM/invalid-because-armv7.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-hint-arm.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-hint-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt delete mode 100644 test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt create mode 100644 test/MC/Disassembler/ARM/invalid-thumbv7-xfail.txt create mode 100644 test/MC/Disassembler/ARM/invalid-thumbv7.txt create mode 100644 test/MC/Disassembler/ARM/invalid-thumbv8.txt create mode 100644 test/MC/Disassembler/ARM/load-store-acquire-release-v8-thumb.txt create mode 100644 test/MC/Disassembler/ARM/load-store-acquire-release-v8.txt create mode 100644 test/MC/Disassembler/ARM/neon-crypto.txt create mode 100644 test/MC/Disassembler/ARM/neon-v8.txt create mode 100644 test/MC/Disassembler/ARM/thumb-fp-armv8.txt create mode 100644 test/MC/Disassembler/ARM/thumb-neon-crypto.txt create mode 100644 test/MC/Disassembler/ARM/thumb-neon-v8.txt create mode 100644 test/MC/Disassembler/ARM/thumb-v8.txt create mode 100644 test/MC/Disassembler/ARM/thumb2-v8.txt delete mode 100644 test/MC/Disassembler/MBlaze/lit.local.cfg delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_branch.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_fpu.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_fsl.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_imm.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_mbar.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_memory.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_operands.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_pattern.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_shift.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_special.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_typea.txt delete mode 100644 test/MC/Disassembler/MBlaze/mblaze_typeb.txt create mode 100644 test/MC/Disassembler/Mips/micromips.txt create mode 100644 test/MC/Disassembler/Mips/micromips_le.txt create mode 100644 test/MC/Disassembler/SystemZ/insns-pcrel.txt create mode 100644 test/MC/Disassembler/SystemZ/insns.txt create mode 100644 test/MC/Disassembler/SystemZ/invalid-regs.txt create mode 100644 test/MC/Disassembler/SystemZ/lit.local.cfg create mode 100644 test/MC/Disassembler/SystemZ/trunc-01.txt create mode 100644 test/MC/Disassembler/SystemZ/trunc-02.txt create mode 100644 test/MC/Disassembler/SystemZ/trunc-03.txt create mode 100644 test/MC/Disassembler/SystemZ/unmapped.txt create mode 100644 test/MC/Disassembler/X86/prefixes.txt create mode 100644 test/MC/ELF/bad-relocation.s create mode 100644 test/MC/ELF/bss-large.ll create mode 100644 test/MC/ELF/cfi-window-save.s create mode 100644 test/MC/ELF/comdat-dup-group-name.s create mode 100644 test/MC/ELF/comdat-reloc.s create mode 100644 test/MC/ELF/debug-line2.s create mode 100644 test/MC/ELF/file-double.s create mode 100644 test/MC/ELF/symbol-names.s delete mode 100644 test/MC/MBlaze/lit.local.cfg delete mode 100644 test/MC/MBlaze/mblaze_branch.s delete mode 100644 test/MC/MBlaze/mblaze_fpu.s delete mode 100644 test/MC/MBlaze/mblaze_fsl.s delete mode 100644 test/MC/MBlaze/mblaze_imm.s delete mode 100644 test/MC/MBlaze/mblaze_memory.s delete mode 100644 test/MC/MBlaze/mblaze_operands.s delete mode 100644 test/MC/MBlaze/mblaze_pattern.s delete mode 100644 test/MC/MBlaze/mblaze_shift.s delete mode 100644 test/MC/MBlaze/mblaze_special.s delete mode 100644 test/MC/MBlaze/mblaze_typea.s delete mode 100644 test/MC/MBlaze/mblaze_typeb.s create mode 100644 test/MC/MachO/bad-darwin-x86_64-32-bit-abs-addr.s create mode 100644 test/MC/MachO/bad-darwin-x86_64-diff-relocs.s create mode 100644 test/MC/MachO/bad-indirect-symbols.s create mode 100644 test/MC/MachO/bss.s create mode 100644 test/MC/MachO/darwin-x86_64-diff-reloc-assign-2.s create mode 100644 test/MC/MachO/tlv-bss.ll create mode 100644 test/MC/Mips/abicalls.ll create mode 100644 test/MC/Mips/elf_eflags.s create mode 100644 test/MC/Mips/elf_st_other.s create mode 100644 test/MC/Mips/micromips-branch-instructions.s create mode 100644 test/MC/Mips/micromips-branch16.s create mode 100644 test/MC/Mips/micromips-expansions.s create mode 100644 test/MC/Mips/micromips-expressions.s create mode 100644 test/MC/Mips/micromips-jump-instructions.s create mode 100644 test/MC/Mips/micromips-jump26.s create mode 100644 test/MC/Mips/micromips-loadstore-unaligned.s create mode 100644 test/MC/Mips/micromips-long-branch.ll create mode 100644 test/MC/Mips/micromips-movcond-instructions.s create mode 100644 test/MC/Mips/micromips-multiply-instructions.s create mode 100644 test/MC/Mips/micromips-relocations.s create mode 100644 test/MC/Mips/micromips-tailr.s create mode 100644 test/MC/Mips/micromips-trap-instructions.s create mode 100644 test/MC/Mips/mips-control-instructions.s create mode 100644 test/MC/Mips/mips-dsp-instructions.s create mode 100644 test/MC/Mips/mips64-instructions.s create mode 100644 test/MC/Mips/msa/test_2r.s create mode 100644 test/MC/Mips/msa/test_2rf.s create mode 100644 test/MC/Mips/msa/test_3r.s create mode 100644 test/MC/Mips/msa/test_3rf.s create mode 100644 test/MC/Mips/msa/test_bit.s create mode 100644 test/MC/Mips/msa/test_cbranch.s create mode 100644 test/MC/Mips/msa/test_ctrlregs.s create mode 100644 test/MC/Mips/msa/test_elm.s create mode 100644 test/MC/Mips/msa/test_elm_insert.s create mode 100644 test/MC/Mips/msa/test_elm_insve.s create mode 100644 test/MC/Mips/msa/test_i10.s create mode 100644 test/MC/Mips/msa/test_i5.s create mode 100644 test/MC/Mips/msa/test_i8.s create mode 100644 test/MC/Mips/msa/test_lsa.s create mode 100644 test/MC/Mips/msa/test_mi10.s create mode 100644 test/MC/Mips/msa/test_vec.s create mode 100644 test/MC/PowerPC/deprecated-p7.s create mode 100644 test/MC/PowerPC/ppc-llong.s create mode 100644 test/MC/PowerPC/ppc-machine.s create mode 100644 test/MC/PowerPC/ppc-nop.s create mode 100644 test/MC/PowerPC/ppc-word.s create mode 100644 test/MC/PowerPC/ppc64-encoding-bookIII.s create mode 100644 test/MC/PowerPC/ppc64-fixup-apply.s create mode 100644 test/MC/PowerPC/ppc64-fixup-explicit.s delete mode 100644 test/MC/PowerPC/ppc64-initial-cfa.ll create mode 100644 test/MC/PowerPC/ppc64-initial-cfa.s create mode 100644 test/MC/PowerPC/ppc64-regs.s delete mode 100644 test/MC/PowerPC/ppc64-relocs-01.ll create mode 100644 test/MC/PowerPC/ppc64-relocs-01.s delete mode 100644 test/MC/PowerPC/ppc64-tls-relocs-01.ll create mode 100644 test/MC/PowerPC/ppc64-tls-relocs-01.s create mode 100644 test/MC/PowerPC/tls-gd-obj.s create mode 100644 test/MC/PowerPC/tls-ie-obj.s create mode 100644 test/MC/PowerPC/tls-ld-obj.s delete mode 100644 test/MC/SystemZ/insn-a-01.s delete mode 100644 test/MC/SystemZ/insn-a-02.s delete mode 100644 test/MC/SystemZ/insn-adb-01.s delete mode 100644 test/MC/SystemZ/insn-adb-02.s delete mode 100644 test/MC/SystemZ/insn-adbr-01.s delete mode 100644 test/MC/SystemZ/insn-aeb-01.s delete mode 100644 test/MC/SystemZ/insn-aeb-02.s delete mode 100644 test/MC/SystemZ/insn-aebr-01.s delete mode 100644 test/MC/SystemZ/insn-afi-01.s delete mode 100644 test/MC/SystemZ/insn-afi-02.s delete mode 100644 test/MC/SystemZ/insn-ag-01.s delete mode 100644 test/MC/SystemZ/insn-ag-02.s delete mode 100644 test/MC/SystemZ/insn-agf-01.s delete mode 100644 test/MC/SystemZ/insn-agf-02.s delete mode 100644 test/MC/SystemZ/insn-agfi-01.s delete mode 100644 test/MC/SystemZ/insn-agfi-02.s delete mode 100644 test/MC/SystemZ/insn-agfr-01.s delete mode 100644 test/MC/SystemZ/insn-aghi-01.s delete mode 100644 test/MC/SystemZ/insn-aghi-02.s delete mode 100644 test/MC/SystemZ/insn-agr-01.s delete mode 100644 test/MC/SystemZ/insn-agsi-01.s delete mode 100644 test/MC/SystemZ/insn-agsi-02.s delete mode 100644 test/MC/SystemZ/insn-ah-01.s delete mode 100644 test/MC/SystemZ/insn-ah-02.s delete mode 100644 test/MC/SystemZ/insn-ahi-01.s delete mode 100644 test/MC/SystemZ/insn-ahi-02.s delete mode 100644 test/MC/SystemZ/insn-ahy-01.s delete mode 100644 test/MC/SystemZ/insn-ahy-02.s delete mode 100644 test/MC/SystemZ/insn-al-01.s delete mode 100644 test/MC/SystemZ/insn-al-02.s delete mode 100644 test/MC/SystemZ/insn-alc-01.s delete mode 100644 test/MC/SystemZ/insn-alc-02.s delete mode 100644 test/MC/SystemZ/insn-alcg-01.s delete mode 100644 test/MC/SystemZ/insn-alcg-02.s delete mode 100644 test/MC/SystemZ/insn-alcgr-01.s delete mode 100644 test/MC/SystemZ/insn-alcr-01.s delete mode 100644 test/MC/SystemZ/insn-alfi-01.s delete mode 100644 test/MC/SystemZ/insn-alfi-02.s delete mode 100644 test/MC/SystemZ/insn-alg-01.s delete mode 100644 test/MC/SystemZ/insn-alg-02.s delete mode 100644 test/MC/SystemZ/insn-algf-01.s delete mode 100644 test/MC/SystemZ/insn-algf-02.s delete mode 100644 test/MC/SystemZ/insn-algfi-01.s delete mode 100644 test/MC/SystemZ/insn-algfi-02.s delete mode 100644 test/MC/SystemZ/insn-algfr-01.s delete mode 100644 test/MC/SystemZ/insn-algr-01.s delete mode 100644 test/MC/SystemZ/insn-alr-01.s delete mode 100644 test/MC/SystemZ/insn-aly-01.s delete mode 100644 test/MC/SystemZ/insn-aly-02.s delete mode 100644 test/MC/SystemZ/insn-ar-01.s delete mode 100644 test/MC/SystemZ/insn-asi-01.s delete mode 100644 test/MC/SystemZ/insn-asi-02.s delete mode 100644 test/MC/SystemZ/insn-axbr-01.s delete mode 100644 test/MC/SystemZ/insn-axbr-02.s delete mode 100644 test/MC/SystemZ/insn-ay-01.s delete mode 100644 test/MC/SystemZ/insn-ay-02.s create mode 100644 test/MC/SystemZ/insn-bad-z196.s create mode 100644 test/MC/SystemZ/insn-bad.s delete mode 100644 test/MC/SystemZ/insn-basr-01.s delete mode 100644 test/MC/SystemZ/insn-br-01.s delete mode 100644 test/MC/SystemZ/insn-bras-01.s delete mode 100644 test/MC/SystemZ/insn-brasl-01.s delete mode 100644 test/MC/SystemZ/insn-brc-01.s delete mode 100644 test/MC/SystemZ/insn-brc-02.s delete mode 100644 test/MC/SystemZ/insn-brcl-01.s delete mode 100644 test/MC/SystemZ/insn-brcl-02.s delete mode 100644 test/MC/SystemZ/insn-c-01.s delete mode 100644 test/MC/SystemZ/insn-c-02.s delete mode 100644 test/MC/SystemZ/insn-cdb-01.s delete mode 100644 test/MC/SystemZ/insn-cdb-02.s delete mode 100644 test/MC/SystemZ/insn-cdbr-01.s delete mode 100644 test/MC/SystemZ/insn-cdfbr-01.s delete mode 100644 test/MC/SystemZ/insn-cdfbr-02.s delete mode 100644 test/MC/SystemZ/insn-cdgbr-01.s delete mode 100644 test/MC/SystemZ/insn-cdgbr-02.s delete mode 100644 test/MC/SystemZ/insn-ceb-01.s delete mode 100644 test/MC/SystemZ/insn-ceb-02.s delete mode 100644 test/MC/SystemZ/insn-cebr-01.s delete mode 100644 test/MC/SystemZ/insn-cefbr-01.s delete mode 100644 test/MC/SystemZ/insn-cefbr-02.s delete mode 100644 test/MC/SystemZ/insn-cegbr-01.s delete mode 100644 test/MC/SystemZ/insn-cegbr-02.s delete mode 100644 test/MC/SystemZ/insn-cfdbr-01.s delete mode 100644 test/MC/SystemZ/insn-cfdbr-02.s delete mode 100644 test/MC/SystemZ/insn-cfebr-01.s delete mode 100644 test/MC/SystemZ/insn-cfebr-02.s delete mode 100644 test/MC/SystemZ/insn-cfi-01.s delete mode 100644 test/MC/SystemZ/insn-cfi-02.s delete mode 100644 test/MC/SystemZ/insn-cfxbr-01.s delete mode 100644 test/MC/SystemZ/insn-cfxbr-02.s delete mode 100644 test/MC/SystemZ/insn-cg-01.s delete mode 100644 test/MC/SystemZ/insn-cg-02.s delete mode 100644 test/MC/SystemZ/insn-cgdbr-01.s delete mode 100644 test/MC/SystemZ/insn-cgdbr-02.s delete mode 100644 test/MC/SystemZ/insn-cgebr-01.s delete mode 100644 test/MC/SystemZ/insn-cgebr-02.s delete mode 100644 test/MC/SystemZ/insn-cgf-01.s delete mode 100644 test/MC/SystemZ/insn-cgf-02.s delete mode 100644 test/MC/SystemZ/insn-cgfi-01.s delete mode 100644 test/MC/SystemZ/insn-cgfi-02.s delete mode 100644 test/MC/SystemZ/insn-cgfr-01.s delete mode 100644 test/MC/SystemZ/insn-cgfrl-01.s delete mode 100644 test/MC/SystemZ/insn-cgh-01.s delete mode 100644 test/MC/SystemZ/insn-cgh-02.s delete mode 100644 test/MC/SystemZ/insn-cghi-01.s delete mode 100644 test/MC/SystemZ/insn-cghi-02.s delete mode 100644 test/MC/SystemZ/insn-cghrl-01.s delete mode 100644 test/MC/SystemZ/insn-cghsi-01.s delete mode 100644 test/MC/SystemZ/insn-cghsi-02.s delete mode 100644 test/MC/SystemZ/insn-cgr-01.s delete mode 100644 test/MC/SystemZ/insn-cgrl-01.s delete mode 100644 test/MC/SystemZ/insn-cgxbr-01.s delete mode 100644 test/MC/SystemZ/insn-cgxbr-02.s delete mode 100644 test/MC/SystemZ/insn-ch-01.s delete mode 100644 test/MC/SystemZ/insn-ch-02.s delete mode 100644 test/MC/SystemZ/insn-chhsi-01.s delete mode 100644 test/MC/SystemZ/insn-chhsi-02.s delete mode 100644 test/MC/SystemZ/insn-chi-01.s delete mode 100644 test/MC/SystemZ/insn-chi-02.s delete mode 100644 test/MC/SystemZ/insn-chrl-01.s delete mode 100644 test/MC/SystemZ/insn-chsi-01.s delete mode 100644 test/MC/SystemZ/insn-chsi-02.s delete mode 100644 test/MC/SystemZ/insn-chy-01.s delete mode 100644 test/MC/SystemZ/insn-chy-02.s delete mode 100644 test/MC/SystemZ/insn-cl-01.s delete mode 100644 test/MC/SystemZ/insn-cl-02.s delete mode 100644 test/MC/SystemZ/insn-clfhsi-01.s delete mode 100644 test/MC/SystemZ/insn-clfhsi-02.s delete mode 100644 test/MC/SystemZ/insn-clfi-01.s delete mode 100644 test/MC/SystemZ/insn-clfi-02.s delete mode 100644 test/MC/SystemZ/insn-clg-01.s delete mode 100644 test/MC/SystemZ/insn-clg-02.s delete mode 100644 test/MC/SystemZ/insn-clgf-01.s delete mode 100644 test/MC/SystemZ/insn-clgf-02.s delete mode 100644 test/MC/SystemZ/insn-clgfi-01.s delete mode 100644 test/MC/SystemZ/insn-clgfi-02.s delete mode 100644 test/MC/SystemZ/insn-clgfr-01.s delete mode 100644 test/MC/SystemZ/insn-clgfrl-01.s delete mode 100644 test/MC/SystemZ/insn-clghrl-01.s delete mode 100644 test/MC/SystemZ/insn-clghsi-01.s delete mode 100644 test/MC/SystemZ/insn-clghsi-02.s delete mode 100644 test/MC/SystemZ/insn-clgr-01.s delete mode 100644 test/MC/SystemZ/insn-clgrl-01.s delete mode 100644 test/MC/SystemZ/insn-clhhsi-01.s delete mode 100644 test/MC/SystemZ/insn-clhhsi-02.s delete mode 100644 test/MC/SystemZ/insn-clhrl-01.s delete mode 100644 test/MC/SystemZ/insn-cli-01.s delete mode 100644 test/MC/SystemZ/insn-cli-02.s delete mode 100644 test/MC/SystemZ/insn-cliy-01.s delete mode 100644 test/MC/SystemZ/insn-cliy-02.s delete mode 100644 test/MC/SystemZ/insn-clr-01.s delete mode 100644 test/MC/SystemZ/insn-clrl-01.s delete mode 100644 test/MC/SystemZ/insn-cly-01.s delete mode 100644 test/MC/SystemZ/insn-cly-02.s delete mode 100644 test/MC/SystemZ/insn-cpsdr-01.s delete mode 100644 test/MC/SystemZ/insn-cr-01.s delete mode 100644 test/MC/SystemZ/insn-crl-01.s delete mode 100644 test/MC/SystemZ/insn-cs-01.s delete mode 100644 test/MC/SystemZ/insn-cs-02.s delete mode 100644 test/MC/SystemZ/insn-csg-01.s delete mode 100644 test/MC/SystemZ/insn-csg-02.s delete mode 100644 test/MC/SystemZ/insn-csy-01.s delete mode 100644 test/MC/SystemZ/insn-csy-02.s delete mode 100644 test/MC/SystemZ/insn-cxbr-01.s delete mode 100644 test/MC/SystemZ/insn-cxbr-02.s delete mode 100644 test/MC/SystemZ/insn-cxfbr-01.s delete mode 100644 test/MC/SystemZ/insn-cxfbr-02.s delete mode 100644 test/MC/SystemZ/insn-cxgbr-01.s delete mode 100644 test/MC/SystemZ/insn-cxgbr-02.s delete mode 100644 test/MC/SystemZ/insn-cy-01.s delete mode 100644 test/MC/SystemZ/insn-cy-02.s delete mode 100644 test/MC/SystemZ/insn-ddb-01.s delete mode 100644 test/MC/SystemZ/insn-ddb-02.s delete mode 100644 test/MC/SystemZ/insn-ddbr-01.s delete mode 100644 test/MC/SystemZ/insn-deb-01.s delete mode 100644 test/MC/SystemZ/insn-deb-02.s delete mode 100644 test/MC/SystemZ/insn-debr-01.s delete mode 100644 test/MC/SystemZ/insn-dl-01.s delete mode 100644 test/MC/SystemZ/insn-dl-02.s delete mode 100644 test/MC/SystemZ/insn-dlg-01.s delete mode 100644 test/MC/SystemZ/insn-dlg-02.s delete mode 100644 test/MC/SystemZ/insn-dlgr-01.s delete mode 100644 test/MC/SystemZ/insn-dlgr-02.s delete mode 100644 test/MC/SystemZ/insn-dlr-01.s delete mode 100644 test/MC/SystemZ/insn-dlr-02.s delete mode 100644 test/MC/SystemZ/insn-dsg-01.s delete mode 100644 test/MC/SystemZ/insn-dsg-02.s delete mode 100644 test/MC/SystemZ/insn-dsgf-01.s delete mode 100644 test/MC/SystemZ/insn-dsgf-02.s delete mode 100644 test/MC/SystemZ/insn-dsgfr-01.s delete mode 100644 test/MC/SystemZ/insn-dsgfr-02.s delete mode 100644 test/MC/SystemZ/insn-dsgr-01.s delete mode 100644 test/MC/SystemZ/insn-dsgr-02.s delete mode 100644 test/MC/SystemZ/insn-dxbr-01.s delete mode 100644 test/MC/SystemZ/insn-dxbr-02.s delete mode 100644 test/MC/SystemZ/insn-ear-01.s delete mode 100644 test/MC/SystemZ/insn-ear-02.s delete mode 100644 test/MC/SystemZ/insn-fidbr-01.s delete mode 100644 test/MC/SystemZ/insn-fidbr-02.s delete mode 100644 test/MC/SystemZ/insn-fiebr-01.s delete mode 100644 test/MC/SystemZ/insn-fiebr-02.s delete mode 100644 test/MC/SystemZ/insn-fixbr-01.s delete mode 100644 test/MC/SystemZ/insn-fixbr-02.s delete mode 100644 test/MC/SystemZ/insn-flogr-01.s delete mode 100644 test/MC/SystemZ/insn-flogr-02.s create mode 100644 test/MC/SystemZ/insn-good-z196.s create mode 100644 test/MC/SystemZ/insn-good.s delete mode 100644 test/MC/SystemZ/insn-ic-01.s delete mode 100644 test/MC/SystemZ/insn-ic-02.s delete mode 100644 test/MC/SystemZ/insn-icy-01.s delete mode 100644 test/MC/SystemZ/insn-icy-02.s delete mode 100644 test/MC/SystemZ/insn-iihf-01.s delete mode 100644 test/MC/SystemZ/insn-iihf-02.s delete mode 100644 test/MC/SystemZ/insn-iihh-01.s delete mode 100644 test/MC/SystemZ/insn-iihh-02.s delete mode 100644 test/MC/SystemZ/insn-iihl-01.s delete mode 100644 test/MC/SystemZ/insn-iihl-02.s delete mode 100644 test/MC/SystemZ/insn-iilf-01.s delete mode 100644 test/MC/SystemZ/insn-iilf-02.s delete mode 100644 test/MC/SystemZ/insn-iilh-01.s delete mode 100644 test/MC/SystemZ/insn-iilh-02.s delete mode 100644 test/MC/SystemZ/insn-iill-01.s delete mode 100644 test/MC/SystemZ/insn-iill-02.s delete mode 100644 test/MC/SystemZ/insn-l-01.s delete mode 100644 test/MC/SystemZ/insn-l-02.s delete mode 100644 test/MC/SystemZ/insn-la-01.s delete mode 100644 test/MC/SystemZ/insn-la-02.s delete mode 100644 test/MC/SystemZ/insn-larl-01.s delete mode 100644 test/MC/SystemZ/insn-lay-01.s delete mode 100644 test/MC/SystemZ/insn-lay-02.s delete mode 100644 test/MC/SystemZ/insn-lb-01.s delete mode 100644 test/MC/SystemZ/insn-lb-02.s delete mode 100644 test/MC/SystemZ/insn-lbr-01.s delete mode 100644 test/MC/SystemZ/insn-lcdbr-01.s delete mode 100644 test/MC/SystemZ/insn-lcebr-01.s delete mode 100644 test/MC/SystemZ/insn-lcgfr-01.s delete mode 100644 test/MC/SystemZ/insn-lcgr-01.s delete mode 100644 test/MC/SystemZ/insn-lcr-01.s delete mode 100644 test/MC/SystemZ/insn-lcxbr-01.s delete mode 100644 test/MC/SystemZ/insn-lcxbr-02.s delete mode 100644 test/MC/SystemZ/insn-ld-01.s delete mode 100644 test/MC/SystemZ/insn-ld-02.s delete mode 100644 test/MC/SystemZ/insn-ldeb-01.s delete mode 100644 test/MC/SystemZ/insn-ldeb-02.s delete mode 100644 test/MC/SystemZ/insn-ldebr-01.s delete mode 100644 test/MC/SystemZ/insn-ldgr-01.s delete mode 100644 test/MC/SystemZ/insn-ldgr-02.s delete mode 100644 test/MC/SystemZ/insn-ldr-01.s delete mode 100644 test/MC/SystemZ/insn-ldxbr-01.s delete mode 100644 test/MC/SystemZ/insn-ldxbr-02.s delete mode 100644 test/MC/SystemZ/insn-ldy-01.s delete mode 100644 test/MC/SystemZ/insn-ldy-02.s delete mode 100644 test/MC/SystemZ/insn-le-01.s delete mode 100644 test/MC/SystemZ/insn-le-02.s delete mode 100644 test/MC/SystemZ/insn-ledbr-01.s delete mode 100644 test/MC/SystemZ/insn-ler-01.s delete mode 100644 test/MC/SystemZ/insn-lexbr-01.s delete mode 100644 test/MC/SystemZ/insn-lexbr-02.s delete mode 100644 test/MC/SystemZ/insn-ley-01.s delete mode 100644 test/MC/SystemZ/insn-ley-02.s delete mode 100644 test/MC/SystemZ/insn-lg-01.s delete mode 100644 test/MC/SystemZ/insn-lg-02.s delete mode 100644 test/MC/SystemZ/insn-lgb-01.s delete mode 100644 test/MC/SystemZ/insn-lgb-02.s delete mode 100644 test/MC/SystemZ/insn-lgbr-01.s delete mode 100644 test/MC/SystemZ/insn-lgdr-01.s delete mode 100644 test/MC/SystemZ/insn-lgdr-02.s delete mode 100644 test/MC/SystemZ/insn-lgf-01.s delete mode 100644 test/MC/SystemZ/insn-lgf-02.s delete mode 100644 test/MC/SystemZ/insn-lgfi-01.s delete mode 100644 test/MC/SystemZ/insn-lgfi-02.s delete mode 100644 test/MC/SystemZ/insn-lgfr-01.s delete mode 100644 test/MC/SystemZ/insn-lgfrl-01.s delete mode 100644 test/MC/SystemZ/insn-lgh-01.s delete mode 100644 test/MC/SystemZ/insn-lgh-02.s delete mode 100644 test/MC/SystemZ/insn-lghi-01.s delete mode 100644 test/MC/SystemZ/insn-lghi-02.s delete mode 100644 test/MC/SystemZ/insn-lghr-01.s delete mode 100644 test/MC/SystemZ/insn-lghrl-01.s delete mode 100644 test/MC/SystemZ/insn-lgr-01.s delete mode 100644 test/MC/SystemZ/insn-lgrl-01.s delete mode 100644 test/MC/SystemZ/insn-lh-01.s delete mode 100644 test/MC/SystemZ/insn-lh-02.s delete mode 100644 test/MC/SystemZ/insn-lhi-01.s delete mode 100644 test/MC/SystemZ/insn-lhi-02.s delete mode 100644 test/MC/SystemZ/insn-lhr-01.s delete mode 100644 test/MC/SystemZ/insn-lhrl-01.s delete mode 100644 test/MC/SystemZ/insn-lhy-01.s delete mode 100644 test/MC/SystemZ/insn-lhy-02.s delete mode 100644 test/MC/SystemZ/insn-llc-01.s delete mode 100644 test/MC/SystemZ/insn-llc-02.s delete mode 100644 test/MC/SystemZ/insn-llcr-01.s delete mode 100644 test/MC/SystemZ/insn-llgc-01.s delete mode 100644 test/MC/SystemZ/insn-llgc-02.s delete mode 100644 test/MC/SystemZ/insn-llgcr-01.s delete mode 100644 test/MC/SystemZ/insn-llgf-01.s delete mode 100644 test/MC/SystemZ/insn-llgf-02.s delete mode 100644 test/MC/SystemZ/insn-llgfr-01.s delete mode 100644 test/MC/SystemZ/insn-llgfrl-01.s delete mode 100644 test/MC/SystemZ/insn-llgh-01.s delete mode 100644 test/MC/SystemZ/insn-llgh-02.s delete mode 100644 test/MC/SystemZ/insn-llghr-01.s delete mode 100644 test/MC/SystemZ/insn-llghrl-01.s delete mode 100644 test/MC/SystemZ/insn-llh-01.s delete mode 100644 test/MC/SystemZ/insn-llh-02.s delete mode 100644 test/MC/SystemZ/insn-llhr-01.s delete mode 100644 test/MC/SystemZ/insn-llhrl-01.s delete mode 100644 test/MC/SystemZ/insn-llihf-01.s delete mode 100644 test/MC/SystemZ/insn-llihf-02.s delete mode 100644 test/MC/SystemZ/insn-llihh-01.s delete mode 100644 test/MC/SystemZ/insn-llihh-02.s delete mode 100644 test/MC/SystemZ/insn-llihl-01.s delete mode 100644 test/MC/SystemZ/insn-llihl-02.s delete mode 100644 test/MC/SystemZ/insn-llilf-01.s delete mode 100644 test/MC/SystemZ/insn-llilf-02.s delete mode 100644 test/MC/SystemZ/insn-llilh-01.s delete mode 100644 test/MC/SystemZ/insn-llilh-02.s delete mode 100644 test/MC/SystemZ/insn-llill-01.s delete mode 100644 test/MC/SystemZ/insn-llill-02.s delete mode 100644 test/MC/SystemZ/insn-lmg-01.s delete mode 100644 test/MC/SystemZ/insn-lmg-02.s delete mode 100644 test/MC/SystemZ/insn-lndbr-01.s delete mode 100644 test/MC/SystemZ/insn-lnebr-01.s delete mode 100644 test/MC/SystemZ/insn-lnxbr-01.s delete mode 100644 test/MC/SystemZ/insn-lnxbr-02.s delete mode 100644 test/MC/SystemZ/insn-lpdbr-01.s delete mode 100644 test/MC/SystemZ/insn-lpebr-01.s delete mode 100644 test/MC/SystemZ/insn-lpxbr-01.s delete mode 100644 test/MC/SystemZ/insn-lpxbr-02.s delete mode 100644 test/MC/SystemZ/insn-lr-01.s delete mode 100644 test/MC/SystemZ/insn-lrl-01.s delete mode 100644 test/MC/SystemZ/insn-lrv-01.s delete mode 100644 test/MC/SystemZ/insn-lrv-02.s delete mode 100644 test/MC/SystemZ/insn-lrvg-01.s delete mode 100644 test/MC/SystemZ/insn-lrvg-02.s delete mode 100644 test/MC/SystemZ/insn-lrvgr-01.s delete mode 100644 test/MC/SystemZ/insn-lrvr-01.s delete mode 100644 test/MC/SystemZ/insn-lxr-01.s delete mode 100644 test/MC/SystemZ/insn-lxr-02.s delete mode 100644 test/MC/SystemZ/insn-ly-01.s delete mode 100644 test/MC/SystemZ/insn-ly-02.s delete mode 100644 test/MC/SystemZ/insn-lzdr-01.s delete mode 100644 test/MC/SystemZ/insn-lzer-01.s delete mode 100644 test/MC/SystemZ/insn-lzxr-01.s delete mode 100644 test/MC/SystemZ/insn-lzxr-02.s delete mode 100644 test/MC/SystemZ/insn-madb-01.s delete mode 100644 test/MC/SystemZ/insn-madb-02.s delete mode 100644 test/MC/SystemZ/insn-madbr-01.s delete mode 100644 test/MC/SystemZ/insn-maeb-01.s delete mode 100644 test/MC/SystemZ/insn-maeb-02.s delete mode 100644 test/MC/SystemZ/insn-maebr-01.s delete mode 100644 test/MC/SystemZ/insn-mdb-01.s delete mode 100644 test/MC/SystemZ/insn-mdb-02.s delete mode 100644 test/MC/SystemZ/insn-mdbr-01.s delete mode 100644 test/MC/SystemZ/insn-mdeb-01.s delete mode 100644 test/MC/SystemZ/insn-mdeb-02.s delete mode 100644 test/MC/SystemZ/insn-mdebr-01.s delete mode 100644 test/MC/SystemZ/insn-meeb-01.s delete mode 100644 test/MC/SystemZ/insn-meeb-02.s delete mode 100644 test/MC/SystemZ/insn-meebr-01.s delete mode 100644 test/MC/SystemZ/insn-mghi-01.s delete mode 100644 test/MC/SystemZ/insn-mghi-02.s delete mode 100644 test/MC/SystemZ/insn-mh-01.s delete mode 100644 test/MC/SystemZ/insn-mh-02.s delete mode 100644 test/MC/SystemZ/insn-mhi-01.s delete mode 100644 test/MC/SystemZ/insn-mhi-02.s delete mode 100644 test/MC/SystemZ/insn-mhy-01.s delete mode 100644 test/MC/SystemZ/insn-mhy-02.s delete mode 100644 test/MC/SystemZ/insn-mlg-01.s delete mode 100644 test/MC/SystemZ/insn-mlg-02.s delete mode 100644 test/MC/SystemZ/insn-mlgr-01.s delete mode 100644 test/MC/SystemZ/insn-mlgr-02.s delete mode 100644 test/MC/SystemZ/insn-ms-01.s delete mode 100644 test/MC/SystemZ/insn-ms-02.s delete mode 100644 test/MC/SystemZ/insn-msdb-01.s delete mode 100644 test/MC/SystemZ/insn-msdb-02.s delete mode 100644 test/MC/SystemZ/insn-msdbr-01.s delete mode 100644 test/MC/SystemZ/insn-mseb-01.s delete mode 100644 test/MC/SystemZ/insn-mseb-02.s delete mode 100644 test/MC/SystemZ/insn-msebr-01.s delete mode 100644 test/MC/SystemZ/insn-msfi-01.s delete mode 100644 test/MC/SystemZ/insn-msfi-02.s delete mode 100644 test/MC/SystemZ/insn-msg-01.s delete mode 100644 test/MC/SystemZ/insn-msg-02.s delete mode 100644 test/MC/SystemZ/insn-msgf-01.s delete mode 100644 test/MC/SystemZ/insn-msgf-02.s delete mode 100644 test/MC/SystemZ/insn-msgfi-01.s delete mode 100644 test/MC/SystemZ/insn-msgfi-02.s delete mode 100644 test/MC/SystemZ/insn-msgfr-01.s delete mode 100644 test/MC/SystemZ/insn-msgr-01.s delete mode 100644 test/MC/SystemZ/insn-msr-01.s delete mode 100644 test/MC/SystemZ/insn-msy-01.s delete mode 100644 test/MC/SystemZ/insn-msy-02.s delete mode 100644 test/MC/SystemZ/insn-mvghi-01.s delete mode 100644 test/MC/SystemZ/insn-mvghi-02.s delete mode 100644 test/MC/SystemZ/insn-mvhhi-01.s delete mode 100644 test/MC/SystemZ/insn-mvhhi-02.s delete mode 100644 test/MC/SystemZ/insn-mvhi-01.s delete mode 100644 test/MC/SystemZ/insn-mvhi-02.s delete mode 100644 test/MC/SystemZ/insn-mvi-01.s delete mode 100644 test/MC/SystemZ/insn-mvi-02.s delete mode 100644 test/MC/SystemZ/insn-mviy-01.s delete mode 100644 test/MC/SystemZ/insn-mviy-02.s delete mode 100644 test/MC/SystemZ/insn-mxbr-01.s delete mode 100644 test/MC/SystemZ/insn-mxbr-02.s delete mode 100644 test/MC/SystemZ/insn-mxdb-01.s delete mode 100644 test/MC/SystemZ/insn-mxdb-02.s delete mode 100644 test/MC/SystemZ/insn-mxdbr-01.s delete mode 100644 test/MC/SystemZ/insn-mxdbr-02.s delete mode 100644 test/MC/SystemZ/insn-n-01.s delete mode 100644 test/MC/SystemZ/insn-n-02.s delete mode 100644 test/MC/SystemZ/insn-ng-01.s delete mode 100644 test/MC/SystemZ/insn-ng-02.s delete mode 100644 test/MC/SystemZ/insn-ngr-01.s delete mode 100644 test/MC/SystemZ/insn-ni-01.s delete mode 100644 test/MC/SystemZ/insn-ni-02.s delete mode 100644 test/MC/SystemZ/insn-nihf-01.s delete mode 100644 test/MC/SystemZ/insn-nihf-02.s delete mode 100644 test/MC/SystemZ/insn-nihh-01.s delete mode 100644 test/MC/SystemZ/insn-nihh-02.s delete mode 100644 test/MC/SystemZ/insn-nihl-01.s delete mode 100644 test/MC/SystemZ/insn-nihl-02.s delete mode 100644 test/MC/SystemZ/insn-nilf-01.s delete mode 100644 test/MC/SystemZ/insn-nilf-02.s delete mode 100644 test/MC/SystemZ/insn-nilh-01.s delete mode 100644 test/MC/SystemZ/insn-nilh-02.s delete mode 100644 test/MC/SystemZ/insn-nill-01.s delete mode 100644 test/MC/SystemZ/insn-nill-02.s delete mode 100644 test/MC/SystemZ/insn-niy-01.s delete mode 100644 test/MC/SystemZ/insn-niy-02.s delete mode 100644 test/MC/SystemZ/insn-nr-01.s delete mode 100644 test/MC/SystemZ/insn-ny-01.s delete mode 100644 test/MC/SystemZ/insn-ny-02.s delete mode 100644 test/MC/SystemZ/insn-o-01.s delete mode 100644 test/MC/SystemZ/insn-o-02.s delete mode 100644 test/MC/SystemZ/insn-og-01.s delete mode 100644 test/MC/SystemZ/insn-og-02.s delete mode 100644 test/MC/SystemZ/insn-ogr-01.s delete mode 100644 test/MC/SystemZ/insn-oi-01.s delete mode 100644 test/MC/SystemZ/insn-oi-02.s delete mode 100644 test/MC/SystemZ/insn-oihf-01.s delete mode 100644 test/MC/SystemZ/insn-oihf-02.s delete mode 100644 test/MC/SystemZ/insn-oihh-01.s delete mode 100644 test/MC/SystemZ/insn-oihh-02.s delete mode 100644 test/MC/SystemZ/insn-oihl-01.s delete mode 100644 test/MC/SystemZ/insn-oihl-02.s delete mode 100644 test/MC/SystemZ/insn-oilf-01.s delete mode 100644 test/MC/SystemZ/insn-oilf-02.s delete mode 100644 test/MC/SystemZ/insn-oilh-01.s delete mode 100644 test/MC/SystemZ/insn-oilh-02.s delete mode 100644 test/MC/SystemZ/insn-oill-01.s delete mode 100644 test/MC/SystemZ/insn-oill-02.s delete mode 100644 test/MC/SystemZ/insn-oiy-01.s delete mode 100644 test/MC/SystemZ/insn-oiy-02.s delete mode 100644 test/MC/SystemZ/insn-or-01.s delete mode 100644 test/MC/SystemZ/insn-oy-01.s delete mode 100644 test/MC/SystemZ/insn-oy-02.s delete mode 100644 test/MC/SystemZ/insn-risbg-01.s delete mode 100644 test/MC/SystemZ/insn-risbg-02.s delete mode 100644 test/MC/SystemZ/insn-rll-01.s delete mode 100644 test/MC/SystemZ/insn-rll-02.s delete mode 100644 test/MC/SystemZ/insn-rllg-01.s delete mode 100644 test/MC/SystemZ/insn-rllg-02.s delete mode 100644 test/MC/SystemZ/insn-s-01.s delete mode 100644 test/MC/SystemZ/insn-s-02.s delete mode 100644 test/MC/SystemZ/insn-sdb-01.s delete mode 100644 test/MC/SystemZ/insn-sdb-02.s delete mode 100644 test/MC/SystemZ/insn-sdbr-01.s delete mode 100644 test/MC/SystemZ/insn-seb-01.s delete mode 100644 test/MC/SystemZ/insn-seb-02.s delete mode 100644 test/MC/SystemZ/insn-sebr-01.s delete mode 100644 test/MC/SystemZ/insn-sg-01.s delete mode 100644 test/MC/SystemZ/insn-sg-02.s delete mode 100644 test/MC/SystemZ/insn-sgf-01.s delete mode 100644 test/MC/SystemZ/insn-sgf-02.s delete mode 100644 test/MC/SystemZ/insn-sgfr-01.s delete mode 100644 test/MC/SystemZ/insn-sgr-01.s delete mode 100644 test/MC/SystemZ/insn-sl-01.s delete mode 100644 test/MC/SystemZ/insn-sl-02.s delete mode 100644 test/MC/SystemZ/insn-slb-01.s delete mode 100644 test/MC/SystemZ/insn-slb-02.s delete mode 100644 test/MC/SystemZ/insn-slbg-01.s delete mode 100644 test/MC/SystemZ/insn-slbg-02.s delete mode 100644 test/MC/SystemZ/insn-slbgr-01.s delete mode 100644 test/MC/SystemZ/insn-slbr-01.s delete mode 100644 test/MC/SystemZ/insn-slfi-01.s delete mode 100644 test/MC/SystemZ/insn-slfi-02.s delete mode 100644 test/MC/SystemZ/insn-slg-01.s delete mode 100644 test/MC/SystemZ/insn-slg-02.s delete mode 100644 test/MC/SystemZ/insn-slgf-01.s delete mode 100644 test/MC/SystemZ/insn-slgf-02.s delete mode 100644 test/MC/SystemZ/insn-slgfi-01.s delete mode 100644 test/MC/SystemZ/insn-slgfi-02.s delete mode 100644 test/MC/SystemZ/insn-slgfr-01.s delete mode 100644 test/MC/SystemZ/insn-slgr-01.s delete mode 100644 test/MC/SystemZ/insn-sll-01.s delete mode 100644 test/MC/SystemZ/insn-sll-02.s delete mode 100644 test/MC/SystemZ/insn-sllg-01.s delete mode 100644 test/MC/SystemZ/insn-sllg-02.s delete mode 100644 test/MC/SystemZ/insn-slr-01.s delete mode 100644 test/MC/SystemZ/insn-sly-01.s delete mode 100644 test/MC/SystemZ/insn-sly-02.s delete mode 100644 test/MC/SystemZ/insn-sqdb-01.s delete mode 100644 test/MC/SystemZ/insn-sqdb-02.s delete mode 100644 test/MC/SystemZ/insn-sqdbr-01.s delete mode 100644 test/MC/SystemZ/insn-sqeb-01.s delete mode 100644 test/MC/SystemZ/insn-sqeb-02.s delete mode 100644 test/MC/SystemZ/insn-sqebr-01.s delete mode 100644 test/MC/SystemZ/insn-sqxbr-01.s delete mode 100644 test/MC/SystemZ/insn-sqxbr-02.s delete mode 100644 test/MC/SystemZ/insn-sr-01.s delete mode 100644 test/MC/SystemZ/insn-sra-01.s delete mode 100644 test/MC/SystemZ/insn-sra-02.s delete mode 100644 test/MC/SystemZ/insn-srag-01.s delete mode 100644 test/MC/SystemZ/insn-srag-02.s delete mode 100644 test/MC/SystemZ/insn-srl-01.s delete mode 100644 test/MC/SystemZ/insn-srl-02.s delete mode 100644 test/MC/SystemZ/insn-srlg-01.s delete mode 100644 test/MC/SystemZ/insn-srlg-02.s delete mode 100644 test/MC/SystemZ/insn-st-01.s delete mode 100644 test/MC/SystemZ/insn-st-02.s delete mode 100644 test/MC/SystemZ/insn-stc-01.s delete mode 100644 test/MC/SystemZ/insn-stc-02.s delete mode 100644 test/MC/SystemZ/insn-stcy-01.s delete mode 100644 test/MC/SystemZ/insn-stcy-02.s delete mode 100644 test/MC/SystemZ/insn-std-01.s delete mode 100644 test/MC/SystemZ/insn-std-02.s delete mode 100644 test/MC/SystemZ/insn-stdy-01.s delete mode 100644 test/MC/SystemZ/insn-stdy-02.s delete mode 100644 test/MC/SystemZ/insn-ste-01.s delete mode 100644 test/MC/SystemZ/insn-ste-02.s delete mode 100644 test/MC/SystemZ/insn-stey-01.s delete mode 100644 test/MC/SystemZ/insn-stey-02.s delete mode 100644 test/MC/SystemZ/insn-stg-01.s delete mode 100644 test/MC/SystemZ/insn-stg-02.s delete mode 100644 test/MC/SystemZ/insn-stgrl-01.s delete mode 100644 test/MC/SystemZ/insn-sth-01.s delete mode 100644 test/MC/SystemZ/insn-sth-02.s delete mode 100644 test/MC/SystemZ/insn-sthrl-01.s delete mode 100644 test/MC/SystemZ/insn-sthy-01.s delete mode 100644 test/MC/SystemZ/insn-sthy-02.s delete mode 100644 test/MC/SystemZ/insn-stmg-01.s delete mode 100644 test/MC/SystemZ/insn-stmg-02.s delete mode 100644 test/MC/SystemZ/insn-strl-01.s delete mode 100644 test/MC/SystemZ/insn-strv-01.s delete mode 100644 test/MC/SystemZ/insn-strv-02.s delete mode 100644 test/MC/SystemZ/insn-strvg-01.s delete mode 100644 test/MC/SystemZ/insn-strvg-02.s delete mode 100644 test/MC/SystemZ/insn-sty-01.s delete mode 100644 test/MC/SystemZ/insn-sty-02.s delete mode 100644 test/MC/SystemZ/insn-sxbr-01.s delete mode 100644 test/MC/SystemZ/insn-sxbr-02.s delete mode 100644 test/MC/SystemZ/insn-sy-01.s delete mode 100644 test/MC/SystemZ/insn-sy-02.s delete mode 100644 test/MC/SystemZ/insn-x-01.s delete mode 100644 test/MC/SystemZ/insn-x-02.s delete mode 100644 test/MC/SystemZ/insn-xg-01.s delete mode 100644 test/MC/SystemZ/insn-xg-02.s delete mode 100644 test/MC/SystemZ/insn-xgr-01.s delete mode 100644 test/MC/SystemZ/insn-xi-01.s delete mode 100644 test/MC/SystemZ/insn-xi-02.s delete mode 100644 test/MC/SystemZ/insn-xihf-01.s delete mode 100644 test/MC/SystemZ/insn-xihf-02.s delete mode 100644 test/MC/SystemZ/insn-xilf-01.s delete mode 100644 test/MC/SystemZ/insn-xilf-02.s delete mode 100644 test/MC/SystemZ/insn-xiy-01.s delete mode 100644 test/MC/SystemZ/insn-xiy-02.s delete mode 100644 test/MC/SystemZ/insn-xr-01.s delete mode 100644 test/MC/SystemZ/insn-xy-01.s delete mode 100644 test/MC/SystemZ/insn-xy-02.s delete mode 100644 test/MC/SystemZ/regs-01.s delete mode 100644 test/MC/SystemZ/regs-02.s delete mode 100644 test/MC/SystemZ/regs-03.s delete mode 100644 test/MC/SystemZ/regs-04.s delete mode 100644 test/MC/SystemZ/regs-05.s delete mode 100644 test/MC/SystemZ/regs-06.s delete mode 100644 test/MC/SystemZ/regs-07.s delete mode 100644 test/MC/SystemZ/regs-08.s delete mode 100644 test/MC/SystemZ/regs-09.s delete mode 100644 test/MC/SystemZ/regs-10.s delete mode 100644 test/MC/SystemZ/regs-11.s delete mode 100644 test/MC/SystemZ/regs-12.s delete mode 100644 test/MC/SystemZ/regs-13.s delete mode 100644 test/MC/SystemZ/regs-14.s delete mode 100644 test/MC/SystemZ/regs-15.s create mode 100644 test/MC/SystemZ/regs-bad.s create mode 100644 test/MC/SystemZ/regs-good.s create mode 100644 test/MC/SystemZ/tokens.s create mode 100644 test/MC/X86/avx512-encodings.s create mode 100644 test/MC/X86/cfi_def_cfa-crash.s create mode 100644 test/MC/X86/x86_64-hle-encoding.s create mode 100644 test/MC/X86/x86_64-tbm-encoding.s create mode 100644 test/Object/ARM/macho-data-in-code.test create mode 100644 test/Object/Inputs/ELF/BE32.yaml create mode 100644 test/Object/Inputs/ELF/BE64.yaml create mode 100644 test/Object/Inputs/ELF/LE32.yaml create mode 100644 test/Object/Inputs/ELF/LE64.yaml create mode 100644 test/Object/Inputs/GNU.a create mode 100644 test/Object/Inputs/IsNAN.o create mode 100644 test/Object/Inputs/MacOSX.a create mode 100644 test/Object/Inputs/SVR4.a create mode 100644 test/Object/Inputs/archive-test.a-corrupt-symbol-table create mode 100644 test/Object/Inputs/archive-test.a-empty create mode 100644 test/Object/Inputs/archive-test.a-gnu-minimal create mode 100644 test/Object/Inputs/archive-test.a-gnu-no-symtab create mode 100644 test/Object/Inputs/coff_archive_short.lib create mode 100644 test/Object/Inputs/corrupt-version.elf-x86_64 create mode 100644 test/Object/Inputs/corrupt.elf-x86-64 create mode 100755 test/Object/Inputs/elf-reloc-no-sym.x86_64 create mode 100644 test/Object/Inputs/evenlen create mode 100644 test/Object/Inputs/macho-data-in-code.macho-thumbv7 create mode 100755 test/Object/Inputs/macho-universal.x86_64.i386 create mode 100644 test/Object/Inputs/oddlen create mode 100755 test/Object/Inputs/program-headers.mips create mode 100755 test/Object/Inputs/trivial-executable-test.macho-x86-64 create mode 100644 test/Object/Inputs/trivial-object-test2.elf-x86-64 create mode 100644 test/Object/Inputs/very_long_bytecode_file_name.bc create mode 100644 test/Object/Inputs/weak-global-symbol.macho-i386 create mode 100644 test/Object/Inputs/xpg4.a create mode 100644 test/Object/X86/objdump-cfg-invalid-opcode.yaml create mode 100644 test/Object/X86/objdump-cfg-textatomsize.yaml create mode 100644 test/Object/X86/objdump-cfg.yaml create mode 100644 test/Object/X86/objdump-disassembly-symbolic.test create mode 100644 test/Object/ar-create.test create mode 100644 test/Object/archive-delete.test create mode 100644 test/Object/archive-error-tmp.txt create mode 100644 test/Object/archive-extract-dir.test create mode 100644 test/Object/archive-format.test create mode 100644 test/Object/archive-move.test create mode 100644 test/Object/archive-replace-pos.test create mode 100644 test/Object/archive-symtab.test create mode 100644 test/Object/archive-toc.test create mode 100644 test/Object/archive-update.test create mode 100644 test/Object/check_binary_output.ll create mode 100644 test/Object/coff-archive-short.test create mode 100644 test/Object/corrupt.test create mode 100644 test/Object/directory.ll create mode 100644 test/Object/elf-reloc-no-sym.test create mode 100644 test/Object/extract.ll create mode 100644 test/Object/nm-error.test create mode 100644 test/Object/nm-universal-binary.test create mode 100644 test/Object/nm-weak-global-macho.test create mode 100644 test/Object/yaml2obj-elf-bits-endian.test create mode 100644 test/Object/yaml2obj-elf-file-headers.yaml create mode 100644 test/Object/yaml2obj-elf-section-basic.yaml create mode 100644 test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml create mode 100644 test/Object/yaml2obj-elf-symbol-basic.yaml create mode 100755 test/Other/Inputs/TestProg/TestProg delete mode 100644 test/Other/Inputs/llvm-cov.gcda delete mode 100644 test/Other/Inputs/llvm-cov.gcno create mode 100644 test/Other/Inputs/llvm_cov.gcda create mode 100644 test/Other/Inputs/llvm_cov.gcno create mode 100644 test/Other/can-execute.txt create mode 100644 test/Other/constant-fold-gep-address-spaces.ll delete mode 100644 test/Other/lit.local.cfg create mode 100644 test/Other/pipefail.txt create mode 100644 test/Other/umask.ll create mode 100644 test/TableGen/intrinsic-order.td create mode 100644 test/TableGen/intrinsic-varargs.td delete mode 100644 test/Transforms/ADCE/lit.local.cfg delete mode 100644 test/Transforms/ArgumentPromotion/lit.local.cfg create mode 100644 test/Transforms/ArgumentPromotion/reserve-tbaa.ll create mode 100644 test/Transforms/BBVectorize/X86/wr-aliases.ll create mode 100644 test/Transforms/BBVectorize/xcore/no-vector-registers.ll delete mode 100644 test/Transforms/BlockPlacement/basictest.ll delete mode 100644 test/Transforms/BlockPlacement/lit.local.cfg delete mode 100644 test/Transforms/CodeExtractor/lit.local.cfg delete mode 100644 test/Transforms/CodeGenPrepare/lit.local.cfg delete mode 100644 test/Transforms/ConstProp/lit.local.cfg create mode 100644 test/Transforms/ConstantMerge/align.ll delete mode 100644 test/Transforms/ConstantMerge/lit.local.cfg delete mode 100644 test/Transforms/CorrelatedValuePropagation/lit.local.cfg create mode 100644 test/Transforms/DeadArgElim/2013-05-17-VarargsAndBlockAddress.ll create mode 100644 test/Transforms/DeadArgElim/linkage.ll delete mode 100644 test/Transforms/DeadArgElim/lit.local.cfg create mode 100644 test/Transforms/DeadArgElim/returned.ll create mode 100644 test/Transforms/DeadArgElim/variadic_safety.ll create mode 100644 test/Transforms/DeadStoreElimination/inst-limits.ll delete mode 100644 test/Transforms/DeadStoreElimination/lit.local.cfg create mode 100644 test/Transforms/DebugIR/crash.ll create mode 100644 test/Transforms/DebugIR/exception.ll create mode 100644 test/Transforms/DebugIR/function.ll create mode 100644 test/Transforms/DebugIR/simple-addrspace.ll create mode 100644 test/Transforms/DebugIR/simple.ll create mode 100644 test/Transforms/DebugIR/struct.ll create mode 100644 test/Transforms/DebugIR/vector.ll delete mode 100644 test/Transforms/EarlyCSE/lit.local.cfg delete mode 100644 test/Transforms/FunctionAttrs/lit.local.cfg create mode 100644 test/Transforms/FunctionAttrs/readattrs.ll delete mode 100644 test/Transforms/GCOVProfiling/lit.local.cfg create mode 100644 test/Transforms/GVN/cond_br.ll create mode 100644 test/Transforms/GVN/cond_br2.ll delete mode 100644 test/Transforms/GVN/lit.local.cfg create mode 100644 test/Transforms/GVN/pr17732.ll create mode 100644 test/Transforms/GVN/pr17852.ll create mode 100644 test/Transforms/GVN/readattrs.ll delete mode 100644 test/Transforms/GlobalDCE/lit.local.cfg create mode 100644 test/Transforms/GlobalOpt/array-elem-refs.ll create mode 100644 test/Transforms/GlobalOpt/atexit.ll create mode 100644 test/Transforms/GlobalOpt/compiler-used.ll create mode 100644 test/Transforms/GlobalOpt/invariant-nodatalayout.ll delete mode 100644 test/Transforms/GlobalOpt/lit.local.cfg create mode 100644 test/Transforms/GlobalOpt/malloc-promote-3.ll delete mode 100644 test/Transforms/IPConstantProp/lit.local.cfg create mode 100644 test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll create mode 100644 test/Transforms/IndVarSimplify/lftr-extend-const.ll create mode 100644 test/Transforms/IndVarSimplify/lftr-zext.ll delete mode 100644 test/Transforms/IndVarSimplify/lit.local.cfg create mode 100644 test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll create mode 100644 test/Transforms/IndVarSimplify/widen-nsw.ll create mode 100644 test/Transforms/Inline/alloca-merge-align-nodl.ll create mode 100644 test/Transforms/Inline/alloca-merge-align.ll create mode 100644 test/Transforms/Inline/attributes.ll create mode 100644 test/Transforms/Inline/inline-invoke-with-asm-call.ll create mode 100644 test/Transforms/Inline/inline-optnone.ll create mode 100644 test/Transforms/Inline/invoke-cost.ll delete mode 100644 test/Transforms/Inline/lit.local.cfg create mode 100644 test/Transforms/InstCombine/PR7357.ll create mode 100644 test/Transforms/InstCombine/addrspacecast.ll create mode 100644 test/Transforms/InstCombine/bitcast-alias-function.ll create mode 100644 test/Transforms/InstCombine/constant-fold-address-space-pointer.ll create mode 100644 test/Transforms/InstCombine/div-shift-crash.ll create mode 100644 test/Transforms/InstCombine/err-rep-cold.ll create mode 100644 test/Transforms/InstCombine/float-shrink-compare.ll create mode 100644 test/Transforms/InstCombine/fneg-ext.ll create mode 100644 test/Transforms/InstCombine/fold-fops-into-selects.ll create mode 100644 test/Transforms/InstCombine/icmp-logical.ll delete mode 100644 test/Transforms/InstCombine/lit.local.cfg create mode 100644 test/Transforms/InstCombine/multi-size-address-space-pointer.ll create mode 100644 test/Transforms/InstCombine/objsize-address-space.ll create mode 100644 test/Transforms/InstCombine/onehot_merge.ll create mode 100644 test/Transforms/InstCombine/phi-select-constexpr.ll create mode 100644 test/Transforms/InstCombine/pow-3.ll create mode 100644 test/Transforms/InstCombine/pr17827.ll create mode 100644 test/Transforms/InstCombine/select-extractelement.ll create mode 100644 test/Transforms/InstCombine/simplify-libcalls.ll create mode 100644 test/Transforms/InstCombine/sincospi.ll create mode 100644 test/Transforms/InstCombine/vector-mul.ll create mode 100644 test/Transforms/InstCombine/win-math.ll delete mode 100644 test/Transforms/InstSimplify/lit.local.cfg delete mode 100644 test/Transforms/Internalize/2008-05-09-AllButMain.ll delete mode 100644 test/Transforms/Internalize/2008-05-09-AllButMain.ll.apifile create mode 100644 test/Transforms/Internalize/apifile delete mode 100644 test/Transforms/Internalize/available_externally.ll create mode 100644 test/Transforms/Internalize/lists.ll delete mode 100644 test/Transforms/Internalize/lit.local.cfg create mode 100644 test/Transforms/Internalize/used.ll create mode 100644 test/Transforms/JumpThreading/landing-pad.ll delete mode 100644 test/Transforms/JumpThreading/lit.local.cfg delete mode 100644 test/Transforms/LCSSA/lit.local.cfg delete mode 100644 test/Transforms/LICM/lit.local.cfg create mode 100644 test/Transforms/LICM/volatile-alias.ll delete mode 100644 test/Transforms/LoopDeletion/lit.local.cfg create mode 100644 test/Transforms/LoopIdiom/basic-address-space.ll delete mode 100644 test/Transforms/LoopIdiom/lit.local.cfg create mode 100644 test/Transforms/LoopReroll/basic.ll create mode 100644 test/Transforms/LoopReroll/reduction.ll delete mode 100644 test/Transforms/LoopRotate/lit.local.cfg create mode 100644 test/Transforms/LoopSimplify/dup-preds.ll delete mode 100644 test/Transforms/LoopSimplify/lit.local.cfg create mode 100644 test/Transforms/LoopStrengthReduce/addrec-gep-address-space.ll create mode 100644 test/Transforms/LoopStrengthReduce/address-space-loop.ll delete mode 100644 test/Transforms/LoopStrengthReduce/lit.local.cfg create mode 100644 test/Transforms/LoopStrengthReduce/lsr-expand-quadratic.ll create mode 100644 test/Transforms/LoopStrengthReduce/scaling_factor_cost_crash.ll create mode 100644 test/Transforms/LoopStrengthReduce/uglygep-address-space.ll create mode 100644 test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll create mode 100644 test/Transforms/LoopUnroll/PowerPC/lit.local.cfg delete mode 100644 test/Transforms/LoopUnroll/lit.local.cfg delete mode 100644 test/Transforms/LoopUnswitch/lit.local.cfg create mode 100644 test/Transforms/LoopVectorize/ARM/gather-cost.ll create mode 100644 test/Transforms/LoopVectorize/X86/already-vectorized.ll create mode 100644 test/Transforms/LoopVectorize/X86/gather-cost.ll create mode 100644 test/Transforms/LoopVectorize/X86/rauw-bug.ll create mode 100644 test/Transforms/LoopVectorize/X86/tripcount.ll create mode 100644 test/Transforms/LoopVectorize/X86/unroll-pm.ll create mode 100644 test/Transforms/LoopVectorize/XCore/lit.local.cfg create mode 100644 test/Transforms/LoopVectorize/XCore/no-vector-registers.ll create mode 100644 test/Transforms/LoopVectorize/align.ll create mode 100644 test/Transforms/LoopVectorize/debugloc.ll create mode 100644 test/Transforms/LoopVectorize/ee-crash.ll create mode 100644 test/Transforms/LoopVectorize/funcall.ll create mode 100644 test/Transforms/LoopVectorize/hoist-loads.ll create mode 100644 test/Transforms/LoopVectorize/if-conversion-edgemasks.ll create mode 100644 test/Transforms/LoopVectorize/induction.ll create mode 100644 test/Transforms/LoopVectorize/infiniteloop.ll create mode 100644 test/Transforms/LoopVectorize/lifetime.ll delete mode 100644 test/Transforms/LoopVectorize/lit.local.cfg create mode 100644 test/Transforms/LoopVectorize/memdep.ll create mode 100644 test/Transforms/LoopVectorize/metadata-unroll.ll create mode 100644 test/Transforms/LoopVectorize/metadata-width.ll create mode 100644 test/Transforms/LoopVectorize/multiple-address-spaces.ll create mode 100644 test/Transforms/LoopVectorize/opt.ll create mode 100644 test/Transforms/LoopVectorize/reverse_iter.ll create mode 100644 test/Transforms/LoopVectorize/runtime-check-address-space.ll create mode 100644 test/Transforms/LoopVectorize/runtime-check-readonly-address-space.ll create mode 100644 test/Transforms/LoopVectorize/safegep.ll create mode 100644 test/Transforms/LoopVectorize/scev-exitlim-crash.ll create mode 100644 test/Transforms/LoopVectorize/store-shuffle-bug.ll create mode 100644 test/Transforms/LoopVectorize/undef-inst-bug.ll create mode 100644 test/Transforms/LoopVectorize/unroll_novec.ll delete mode 100644 test/Transforms/LowerAtomic/lit.local.cfg delete mode 100644 test/Transforms/LowerExpectIntrinsic/lit.local.cfg delete mode 100644 test/Transforms/LowerInvoke/lit.local.cfg delete mode 100644 test/Transforms/LowerSwitch/lit.local.cfg delete mode 100644 test/Transforms/Mem2Reg/lit.local.cfg delete mode 100644 test/Transforms/MemCpyOpt/lit.local.cfg create mode 100644 test/Transforms/MergeFunc/address-spaces.ll create mode 100644 test/Transforms/MergeFunc/inttoptr-address-space.ll delete mode 100644 test/Transforms/MergeFunc/lit.local.cfg create mode 100644 test/Transforms/MergeFunc/merge-ptr-and-int.ll create mode 100644 test/Transforms/MergeFunc/ptr-int-transitivity-1.ll create mode 100644 test/Transforms/MergeFunc/ptr-int-transitivity-2.ll create mode 100644 test/Transforms/MergeFunc/ptr-int-transitivity-3.ll create mode 100644 test/Transforms/MergeFunc/too-small.ll delete mode 100644 test/Transforms/MetaRenamer/lit.local.cfg create mode 100644 test/Transforms/ObjCARC/allocas.ll delete mode 100644 test/Transforms/ObjCARC/lit.local.cfg delete mode 100644 test/Transforms/ObjCARC/no-objc-arc-exceptions.ll delete mode 100644 test/Transforms/ObjCARC/retain-block-alloca.ll delete mode 100644 test/Transforms/ObjCARC/retain-block-escape-analysis.ll delete mode 100644 test/Transforms/ObjCARC/retain-block-load.ll delete mode 100644 test/Transforms/ObjCARC/retain-block.ll delete mode 100644 test/Transforms/PhaseOrdering/lit.local.cfg delete mode 100644 test/Transforms/PruneEH/lit.local.cfg delete mode 100644 test/Transforms/Reassociate/lit.local.cfg delete mode 100644 test/Transforms/Reg2Mem/lit.local.cfg delete mode 100644 test/Transforms/SCCP/lit.local.cfg create mode 100644 test/Transforms/SLPVectorizer/ARM/lit.local.cfg create mode 100644 test/Transforms/SLPVectorizer/ARM/memory.ll create mode 100644 test/Transforms/SLPVectorizer/ARM/sroa.ll create mode 100644 test/Transforms/SLPVectorizer/R600/lit.local.cfg create mode 100644 test/Transforms/SLPVectorizer/R600/simplebb.ll create mode 100644 test/Transforms/SLPVectorizer/X86/cmp_sel.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_7zip.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_bullet.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_bullet3.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_dequeue.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_flop7.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_lencod.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_mandeltext.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_netbsd_decompress.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_sim4b1.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_smallpt.ll create mode 100644 test/Transforms/SLPVectorizer/X86/cross_block_slp.ll create mode 100644 test/Transforms/SLPVectorizer/X86/cse.ll create mode 100644 test/Transforms/SLPVectorizer/X86/cycle_dup.ll create mode 100644 test/Transforms/SLPVectorizer/X86/debug_info.ll create mode 100644 test/Transforms/SLPVectorizer/X86/external_user.ll create mode 100644 test/Transforms/SLPVectorizer/X86/extract.ll create mode 100644 test/Transforms/SLPVectorizer/X86/horizontal.ll create mode 100644 test/Transforms/SLPVectorizer/X86/implicitfloat.ll create mode 100644 test/Transforms/SLPVectorizer/X86/in-tree-user.ll create mode 100644 test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll create mode 100644 test/Transforms/SLPVectorizer/X86/long_chains.ll create mode 100644 test/Transforms/SLPVectorizer/X86/multi_block.ll create mode 100644 test/Transforms/SLPVectorizer/X86/odd_store.ll create mode 100644 test/Transforms/SLPVectorizer/X86/operandorder.ll create mode 100644 test/Transforms/SLPVectorizer/X86/opt.ll create mode 100644 test/Transforms/SLPVectorizer/X86/ordering.ll create mode 100644 test/Transforms/SLPVectorizer/X86/phi.ll create mode 100644 test/Transforms/SLPVectorizer/X86/phi3.ll create mode 100644 test/Transforms/SLPVectorizer/X86/phi_landingpad.ll create mode 100644 test/Transforms/SLPVectorizer/X86/phi_overalignedtype.ll create mode 100644 test/Transforms/SLPVectorizer/X86/pr16571.ll create mode 100644 test/Transforms/SLPVectorizer/X86/pr16628.ll create mode 100644 test/Transforms/SLPVectorizer/X86/pr16899.ll create mode 100644 test/Transforms/SLPVectorizer/X86/pr18060.ll create mode 100644 test/Transforms/SLPVectorizer/X86/rgb_phi.ll create mode 100644 test/Transforms/SLPVectorizer/X86/tiny-tree.ll create mode 100644 test/Transforms/SLPVectorizer/XCore/lit.local.cfg create mode 100644 test/Transforms/SLPVectorizer/XCore/no-vector-registers.ll delete mode 100644 test/Transforms/SLPVectorizer/lit.local.cfg delete mode 100644 test/Transforms/SROA/lit.local.cfg create mode 100644 test/Transforms/SROA/vector-conversion.ll create mode 100644 test/Transforms/SampleProfile/Inputs/branch.prof create mode 100644 test/Transforms/SampleProfile/branch.ll delete mode 100644 test/Transforms/ScalarRepl/lit.local.cfg create mode 100644 test/Transforms/SimplifyCFG/CoveredLookupTable.ll create mode 100644 test/Transforms/SimplifyCFG/PR16069.ll create mode 100644 test/Transforms/SimplifyCFG/attr-noduplicate.ll create mode 100644 test/Transforms/SimplifyCFG/common-dest-folding.ll delete mode 100644 test/Transforms/SimplifyCFG/lit.local.cfg delete mode 100644 test/Transforms/SimplifyLibCalls/2005-05-20-sprintf-crash.ll delete mode 100644 test/Transforms/SimplifyLibCalls/2007-04-06-strchr-miscompile.ll delete mode 100644 test/Transforms/SimplifyLibCalls/2008-05-19-memcmp.ll delete mode 100644 test/Transforms/SimplifyLibCalls/2009-05-30-memcmp-byte.ll delete mode 100644 test/Transforms/SimplifyLibCalls/2009-07-28-Exit.ll delete mode 100644 test/Transforms/SimplifyLibCalls/2009-07-29-Exit2.ll delete mode 100644 test/Transforms/SimplifyLibCalls/MemCpy.ll delete mode 100644 test/Transforms/SimplifyLibCalls/PR7357.ll delete mode 100644 test/Transforms/SimplifyLibCalls/float-shrink-compare.ll delete mode 100644 test/Transforms/SimplifyLibCalls/lit.local.cfg delete mode 100644 test/Transforms/SimplifyLibCalls/win-math.ll delete mode 100644 test/Transforms/Sink/lit.local.cfg delete mode 100644 test/Transforms/StripSymbols/2010-07-01-DeadDbgInfo.ll delete mode 100644 test/Transforms/StripSymbols/lit.local.cfg create mode 100644 test/Transforms/StripSymbols/strip-dead-debug-info.ll create mode 100644 test/Transforms/StructurizeCFG/branch-on-argument.ll create mode 100644 test/Transforms/StructurizeCFG/loop-multiple-exits.ll create mode 100644 test/Transforms/StructurizeCFG/no-branch-to-entry.ll create mode 100644 test/Transforms/StructurizeCFG/switch.ll create mode 100644 test/Transforms/TailCallElim/basic.ll delete mode 100644 test/Transforms/TailCallElim/dont-tce-tail-marked-call.ll delete mode 100644 test/Transforms/TailCallElim/intervening-inst.ll delete mode 100644 test/Transforms/TailCallElim/lit.local.cfg delete mode 100644 test/Transforms/TailCallElim/move_alloca_for_tail_call.ll delete mode 100644 test/Transforms/TailCallElim/nocapture.ll delete mode 100644 test/Transforms/TailCallElim/return_constant.ll delete mode 100644 test/Transforms/TailCallElim/trivial_codegen_tailcall.ll create mode 100644 test/Verifier/bitcast-address-space-nested-global-cycle.ll create mode 100644 test/Verifier/bitcast-address-space-nested-global.ll create mode 100644 test/Verifier/bitcast-address-space-through-constant-inttoptr-inside-gep-instruction.ll create mode 100644 test/Verifier/bitcast-address-space-through-constant-inttoptr.ll create mode 100644 test/Verifier/bitcast-address-space-through-gep-2.ll create mode 100644 test/Verifier/bitcast-address-space-through-gep.ll create mode 100644 test/Verifier/bitcast-address-space-through-inttoptr.ll create mode 100644 test/Verifier/bitcast-address-spaces.ll create mode 100644 test/Verifier/bitcast-alias-address-space.ll create mode 100644 test/Verifier/bitcast-vector-pointer-as.ll create mode 100644 test/Verifier/ident-meta1.ll create mode 100644 test/Verifier/ident-meta2.ll create mode 100644 test/Verifier/ident-meta3.ll delete mode 100644 test/Verifier/lit.local.cfg create mode 100644 test/Verifier/varargs-intrinsic.ll create mode 100644 test/tools/llvm-cov/Inputs/README create mode 100644 test/tools/llvm-cov/Inputs/test.cpp create mode 100644 test/tools/llvm-cov/Inputs/test.cpp.gcov create mode 100644 test/tools/llvm-cov/Inputs/test.gcda create mode 100644 test/tools/llvm-cov/Inputs/test.gcno create mode 100644 test/tools/llvm-cov/Inputs/test_read_fail.gcno create mode 100644 test/tools/llvm-cov/lit.local.cfg create mode 100644 test/tools/llvm-cov/llvm-cov.test delete mode 100644 test/tools/llvm-lit/lit.local.cfg create mode 100644 test/tools/llvm-objdump/Inputs/nop.exe.coff-i386 create mode 100644 test/tools/llvm-objdump/Inputs/trivial.obj.elf-i386 create mode 100644 test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64 create mode 100644 test/tools/llvm-objdump/Inputs/win64-unwind.exe.coff-x86_64.asm create mode 100644 test/tools/llvm-objdump/coff-private-headers.test delete mode 100644 test/tools/llvm-objdump/disassembly-show-raw.s create mode 100644 test/tools/llvm-objdump/disassembly-show-raw.test delete mode 100644 test/tools/llvm-objdump/win64-unwind-data.s create mode 100644 test/tools/llvm-objdump/win64-unwind-data.test create mode 100644 test/tools/llvm-readobj/Inputs/dynamic-table.c create mode 100644 test/tools/llvm-readobj/Inputs/dynamic-table.mips create mode 100644 test/tools/llvm-readobj/Inputs/magic.coff-importlib create mode 100644 test/tools/llvm-readobj/Inputs/magic.coff-unknown create mode 100644 test/tools/llvm-readobj/Inputs/rpath.exe.elf-x86_64 create mode 100644 test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386 create mode 100644 test/tools/llvm-readobj/dynamic.test delete mode 100644 test/tools/llvm-readobj/lit.local.cfg create mode 100644 test/tools/llvm-readobj/rpath.test create mode 100644 tools/lli/ChildTarget/CMakeLists.txt create mode 100644 tools/lli/ChildTarget/ChildTarget.cpp create mode 100644 tools/lli/ChildTarget/LLVMBuild.txt create mode 100644 tools/lli/ChildTarget/Makefile create mode 100644 tools/lli/ChildTarget/Unix/ChildTarget.inc create mode 100644 tools/lli/ChildTarget/Windows/ChildTarget.inc delete mode 100644 tools/lli/RecordingMemoryManager.cpp delete mode 100644 tools/lli/RecordingMemoryManager.h create mode 100644 tools/lli/RemoteMemoryManager.cpp create mode 100644 tools/lli/RemoteMemoryManager.h create mode 100644 tools/lli/RemoteTargetExternal.cpp create mode 100644 tools/lli/RemoteTargetExternal.h create mode 100644 tools/lli/RemoteTargetMessage.h create mode 100644 tools/lli/Unix/RemoteTargetExternal.inc create mode 100644 tools/lli/Windows/RemoteTargetExternal.inc create mode 100644 tools/llvm-c-test/CMakeLists.txt create mode 100644 tools/llvm-c-test/Makefile create mode 100644 tools/llvm-c-test/calc.c create mode 100644 tools/llvm-c-test/disassemble.c create mode 100644 tools/llvm-c-test/helpers.c create mode 100644 tools/llvm-c-test/include-all.c create mode 100644 tools/llvm-c-test/llvm-c-test.h create mode 100644 tools/llvm-c-test/main.c create mode 100644 tools/llvm-c-test/module.c create mode 100644 tools/llvm-c-test/object.c create mode 100644 tools/llvm-c-test/targets.c create mode 100644 tools/llvm-lto/CMakeLists.txt create mode 100644 tools/llvm-lto/LLVMBuild.txt create mode 100644 tools/llvm-lto/Makefile create mode 100644 tools/llvm-lto/llvm-lto.cpp delete mode 100644 tools/llvm-objdump/MCFunction.cpp delete mode 100644 tools/llvm-objdump/MCFunction.h delete mode 100644 tools/llvm-prof/CMakeLists.txt delete mode 100644 tools/llvm-prof/LLVMBuild.txt delete mode 100644 tools/llvm-prof/Makefile delete mode 100644 tools/llvm-prof/llvm-prof.cpp delete mode 100644 tools/llvm-ranlib/CMakeLists.txt delete mode 100644 tools/llvm-ranlib/LLVMBuild.txt delete mode 100644 tools/llvm-ranlib/Makefile delete mode 100644 tools/llvm-ranlib/llvm-ranlib.cpp delete mode 100644 tools/lto/LTOCodeGenerator.cpp delete mode 100644 tools/lto/LTOCodeGenerator.h delete mode 100644 tools/lto/LTOModule.cpp delete mode 100644 tools/lto/LTOModule.h create mode 100644 tools/msbuild/CMakeLists.txt create mode 100644 tools/msbuild/Microsoft.Cpp.Win32.LLVM-vs2010.targets create mode 100644 tools/msbuild/Microsoft.Cpp.Win32.LLVM-vs2012.targets create mode 100644 tools/msbuild/Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets create mode 100644 tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in create mode 100644 tools/msbuild/install.bat create mode 100644 tools/msbuild/toolset-vs2013.targets create mode 100644 tools/msbuild/toolset-vs2013_xp.targets create mode 100644 tools/msbuild/uninstall.bat create mode 100644 tools/yaml2obj/yaml2coff.cpp create mode 100644 tools/yaml2obj/yaml2elf.cpp create mode 100644 tools/yaml2obj/yaml2obj.h create mode 100644 unittests/ADT/PointerUnionTest.cpp create mode 100644 unittests/ADT/polymorphic_ptr_test.cpp create mode 100644 unittests/Analysis/CFGTest.cpp create mode 100644 unittests/CodeGen/CMakeLists.txt create mode 100644 unittests/CodeGen/DIEHashTest.cpp create mode 100644 unittests/CodeGen/Makefile create mode 100644 unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp create mode 100644 unittests/IR/LegacyPassManagerTest.cpp create mode 100644 unittests/MC/CMakeLists.txt create mode 100644 unittests/MC/MCAtomTest.cpp create mode 100644 unittests/MC/Makefile create mode 100644 unittests/Object/CMakeLists.txt create mode 100644 unittests/Object/Makefile create mode 100644 unittests/Object/YAMLTest.cpp create mode 100644 unittests/Option/Makefile create mode 100644 unittests/Support/ConvertUTFTest.cpp delete mode 100644 unittests/Support/IntegersSubsetTest.cpp create mode 100644 unittests/Support/LockFileManagerTest.cpp create mode 100644 unittests/Support/MD5Test.cpp create mode 100644 unittests/Support/SourceMgrTest.cpp create mode 100644 unittests/Support/ThreadLocalTest.cpp delete mode 100644 unittests/Support/TimeValue.cpp create mode 100644 unittests/Support/TimeValueTest.cpp create mode 100644 unittests/Support/UnicodeTest.cpp create mode 100644 unittests/Transforms/DebugIR/CMakeLists.txt create mode 100644 unittests/Transforms/DebugIR/DebugIR.cpp create mode 100644 unittests/Transforms/DebugIR/Makefile create mode 100644 unittests/Transforms/Utils/SpecialCaseList.cpp create mode 100644 utils/Misc/mergefunctions.clang.svn.patch delete mode 100644 utils/TableGen/StringToOffsetTable.h create mode 100644 utils/lit/examples/README.txt create mode 100644 utils/lit/examples/many-tests/README.txt create mode 100644 utils/lit/examples/many-tests/lit.cfg delete mode 100644 utils/lit/lit/ExampleTests/Clang/fsyntax-only.c delete mode 100644 utils/lit/lit/ExampleTests/Clang/lit.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/data.txt delete mode 100644 utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/pct-S.ll delete mode 100644 utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll delete mode 100644 utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg delete mode 100644 utils/lit/lit/ExampleTests/ManyTests/lit.local.cfg delete mode 100644 utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg delete mode 100644 utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg delete mode 100644 utils/lit/lit/ExampleTests/fail.c delete mode 100644 utils/lit/lit/ExampleTests/lit.cfg delete mode 100644 utils/lit/lit/ExampleTests/pass.c delete mode 100644 utils/lit/lit/ExampleTests/required-and-missing.c delete mode 100644 utils/lit/lit/ExampleTests/required-and-present.c delete mode 100644 utils/lit/lit/ExampleTests/vg-fail.c delete mode 100644 utils/lit/lit/ExampleTests/xfail-feature.c delete mode 100644 utils/lit/lit/ExampleTests/xfail.c delete mode 100644 utils/lit/lit/ExampleTests/xpass.c delete mode 100644 utils/lit/lit/TestFormats.py delete mode 100644 utils/lit/lit/Util.py create mode 100644 utils/lit/lit/formats/__init__.py create mode 100644 utils/lit/lit/formats/base.py create mode 100644 utils/lit/lit/formats/googletest.py create mode 100644 utils/lit/lit/formats/shtest.py create mode 100644 utils/lit/lit/run.py create mode 100644 utils/lit/lit/util.py create mode 100755 utils/lit/tests/Inputs/googletest-format/DummySubDir/OneTest create mode 100644 utils/lit/tests/Inputs/googletest-format/lit.cfg create mode 100644 utils/lit/tests/Inputs/shtest-format/argv0.txt create mode 100644 utils/lit/tests/Inputs/shtest-format/external_shell/fail_with_bad_encoding.txt create mode 100755 utils/lit/tests/Inputs/shtest-format/external_shell/write-bad-encoding.sh create mode 100644 utils/lit/tests/Inputs/test-data/lit.cfg create mode 100644 utils/lit/tests/Inputs/test-data/metrics.ini create mode 100644 utils/lit/tests/googletest-format.py create mode 100644 utils/lit/tests/shtest-encoding.py create mode 100644 utils/lit/tests/test-data.py create mode 100644 utils/lit/tests/test-output.py delete mode 100755 utils/profile.pl create mode 100755 utils/release/export.sh delete mode 100644 utils/unittest/googletest/gtest-all.cc delete mode 100644 utils/unittest/googletest/gtest-death-test.cc delete mode 100644 utils/unittest/googletest/gtest-filepath.cc delete mode 100644 utils/unittest/googletest/gtest-port.cc delete mode 100644 utils/unittest/googletest/gtest-printers.cc delete mode 100644 utils/unittest/googletest/gtest-test-part.cc delete mode 100644 utils/unittest/googletest/gtest-typed-test.cc delete mode 100644 utils/unittest/googletest/gtest.cc delete mode 100644 utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h create mode 100644 utils/unittest/googletest/src/gtest-all.cc create mode 100644 utils/unittest/googletest/src/gtest-death-test.cc create mode 100644 utils/unittest/googletest/src/gtest-filepath.cc create mode 100644 utils/unittest/googletest/src/gtest-internal-inl.h create mode 100644 utils/unittest/googletest/src/gtest-port.cc create mode 100644 utils/unittest/googletest/src/gtest-printers.cc create mode 100644 utils/unittest/googletest/src/gtest-test-part.cc create mode 100644 utils/unittest/googletest/src/gtest-typed-test.cc create mode 100644 utils/unittest/googletest/src/gtest.cc diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000..9b3aa8b7213b2 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/CMakeLists.txt b/CMakeLists.txt index fffdf9b87be6a..a68e7e163c524 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,13 @@ set(CMAKE_MODULE_PATH ) set(LLVM_VERSION_MAJOR 3) -set(LLVM_VERSION_MINOR 3) +set(LLVM_VERSION_MINOR 4) -set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}svn") +if (NOT PACKAGE_VERSION) + set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}svn") +endif() + +option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) option(LLVM_USE_FOLDERS "Enable solution folders in Visual Studio. Disable for Express versions." ON) if ( LLVM_USE_FOLDERS ) @@ -33,6 +37,25 @@ set(PACKAGE_NAME LLVM) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "http://llvm.org/bugs/") +# Configure CPack. +set(CPACK_PACKAGE_INSTALL_DIRECTORY "LLVM") +set(CPACK_PACKAGE_VENDOR "LLVM") +set(CPACK_PACKAGE_VERSION_MAJOR ${LLVM_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${LLVM_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.TXT") +if(WIN32 AND NOT UNIX) + set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "LLVM") + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\cmake\\\\nsis_logo.bmp") + set(CPACK_NSIS_MODIFY_PATH "ON") + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS + "ExecWait '$INSTDIR/tools/msbuild/install.bat'") + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS + "ExecWait '$INSTDIR/tools/msbuild/uninstall.bat'") +endif() +include(CPack) + # Sanity check our source directory to make sure that we are not trying to # generate an in-tree build (unless on MSVC_IDE, where it is ok), and to make # sure that we don't have any stray generated files lying around in the tree @@ -79,10 +102,10 @@ set(LLVM_ALL_TARGETS CppBackend Hexagon Mips - MBlaze MSP430 NVPTX PowerPC + R600 Sparc SystemZ X86 @@ -90,7 +113,7 @@ set(LLVM_ALL_TARGETS ) # List of targets with JIT support: -set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM Mips SystemZ) +set(LLVM_TARGETS_WITH_JIT X86 PowerPC AArch64 ARM Mips SystemZ) set(LLVM_TARGETS_TO_BUILD "all" CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") @@ -116,6 +139,11 @@ if(LLVM_ENABLE_BACKTRACES) set(ENABLE_BACKTRACES 1) endif() +option(LLVM_ENABLE_CRASH_OVERRIDES "Enable crash overrides." ON) +if(LLVM_ENABLE_CRASH_OVERRIDES) + set(ENABLE_CRASH_OVERRIDES 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") @@ -123,6 +151,8 @@ set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should sear set(LLVM_TARGET_ARCH "host" CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.") +option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON) + option(LLVM_ENABLE_THREADS "Use threads if available." ON) option(LLVM_ENABLE_ZLIB "Use zlib for compression/decompression if available." ON) @@ -134,18 +164,7 @@ endif() set(LLVM_TARGETS_TO_BUILD ${LLVM_TARGETS_TO_BUILD} ${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}) - -set(LLVM_ENUM_TARGETS "") -foreach(c ${LLVM_TARGETS_TO_BUILD}) - list(FIND LLVM_ALL_TARGETS ${c} idx) - list(FIND LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${c} idy) - if( idx LESS 0 AND idy 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) +list(REMOVE_DUPLICATES LLVM_TARGETS_TO_BUILD) set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm) @@ -163,7 +182,7 @@ 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" ) +if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF) else() option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON) @@ -194,6 +213,9 @@ endif( LLVM_USE_OPROFILE ) set(LLVM_USE_SANITIZER "" CACHE STRING "Define the sanitizer used to build binaries and tests.") +option(LLVM_USE_SPLIT_DWARF + "Use -gsplit-dwarf when compiling llvm." OFF) + # Define an option controlling whether we should build for 32-bit on 64-bit # platforms, where supported. if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) @@ -215,18 +237,15 @@ if( WIN32 AND NOT CYGWIN ) endif() # Define options to control the inclusion and default build behavior for -# components which may not strictly be necessary (tools, runtime, examples, and -# tests). +# components which may not strictly be necessary (tools, examples, and tests). # # This is primarily to support building smaller or faster project files. option(LLVM_INCLUDE_TOOLS "Generate build targets for the LLVM tools." ON) option(LLVM_BUILD_TOOLS "Build the LLVM tools. If OFF, just generate build targets." ON) -option(LLVM_INCLUDE_RUNTIME "Generate build targets for the LLVM runtimes" ON) option(LLVM_BUILD_RUNTIME - "Build the LLVM runtime libraries. If OFF, just generate build targets." ON) - + "Build the LLVM runtime libraries." ON) 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) @@ -235,6 +254,10 @@ option(LLVM_BUILD_TESTS "Build LLVM unit tests. If OFF, just generate build targets." OFF) option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON) +option (LLVM_BUILD_DOCS "Build the llvm documentation." OFF) +option (LLVM_INCLUDE_DOCS "Generate build targets for llvm documentation." ON) +option (LLVM_ENABLE_DOXYGEN "Use doxygen to generate llvm documentation." OFF) + # All options referred to from HandleLLVMOptions have to be specified # BEFORE this include, otherwise options will not be correctly set on # first cmake run @@ -248,7 +271,8 @@ set(TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}") include(HandleLLVMOptions) -# Verify that we can find a Python interpreter, +# Verify that we can find a Python 2 interpreter. Python 3 is unsupported. +set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) include(FindPythonInterp) if( NOT PYTHONINTERP_FOUND ) message(FATAL_ERROR @@ -293,7 +317,7 @@ execute_process( --enable-optional-components "${LLVMOPTIONALCOMPONENTS}" --write-library-table ${LLVMCONFIGLIBRARYDEPENDENCIESINC} --write-cmake-fragment ${LLVMBUILDCMAKEFRAG} - ERROR_VARIABLE LLVMBUILDOUTPUT + OUTPUT_VARIABLE LLVMBUILDOUTPUT ERROR_VARIABLE LLVMBUILDERRORS OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE @@ -319,11 +343,22 @@ include(${LLVMBUILDCMAKEFRAG}) # Configure all of the various header file fragments LLVM uses which depend on # configuration variables. +set(LLVM_ENUM_TARGETS "") set(LLVM_ENUM_ASM_PRINTERS "") set(LLVM_ENUM_ASM_PARSERS "") set(LLVM_ENUM_DISASSEMBLERS "") foreach(t ${LLVM_TARGETS_TO_BUILD}) set( td ${LLVM_MAIN_SRC_DIR}/lib/Target/${t} ) + + list(FIND LLVM_ALL_TARGETS ${t} idx) + list(FIND LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${t} idy) + if( idx LESS 0 AND idy LESS 0 ) + message(FATAL_ERROR "The target `${t}' does not exist. + It should be one of\n${LLVM_ALL_TARGETS}") + else() + set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${t})\n") + endif() + file(GLOB asmp_file "${td}/*AsmPrinter.cpp") if( asmp_file ) set(LLVM_ENUM_ASM_PRINTERS @@ -424,10 +459,6 @@ if( LLVM_INCLUDE_TOOLS ) add_subdirectory(tools) endif() -if( LLVM_INCLUDE_RUNTIME ) - add_subdirectory(runtime) -endif() - if( LLVM_INCLUDE_EXAMPLES ) add_subdirectory(examples) endif() @@ -457,38 +488,36 @@ if( LLVM_INCLUDE_TESTS ) ) 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 - ) +if (LLVM_INCLUDE_DOCS) + add_subdirectory(docs) +endif() -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 - ) +add_subdirectory(cmake/modules) -# TODO: make and install documentation. +if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.td" + PATTERN "*.inc" + PATTERN "LICENSE.TXT" + PATTERN ".svn" EXCLUDE + ) -set(CPACK_PACKAGE_VENDOR "LLVM") -set(CPACK_PACKAGE_VERSION_MAJOR ${LLVM_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${LLVM_VERSION_MINOR}) -add_version_info_from_vcs(CPACK_PACKAGE_VERSION_PATCH) -include(CPack) + 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 + ) +endif() # Workaround for MSVS10 to avoid the Dialog Hell # FIXME: This could be removed with future version of CMake. @@ -498,3 +527,4 @@ if(MSVC_VERSION EQUAL 1600) file(APPEND "${LLVM_SLN_FILENAME}" "\n# This should be regenerated!\n") endif() endif() + diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index 8e13e35f40333..cffb91b6903d8 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -102,13 +102,17 @@ E: richard@xmos.com D: XCore Backend N: Chad Rosier -E: mcrosier@apple.com +E: mcrosier@codeaurora.org D: Fast-Isel N: Nadav Rotem E: nrotem@apple.com D: X86 Backend, Loop Vectorizer +N: Daniel Sanders +E: daniel.sanders@imgtec.com +D: MIPS Backend (lib/Target/Mips/*) + N: Richard Sandiford E: rsandifo@linux.vnet.ibm.com D: SystemZ Backend @@ -117,6 +121,10 @@ N: Duncan Sands E: baldrick@free.fr D: DragonEgg +N: Kostya Serebryany +E: kcc@google.com +D: AddressSanitizer, ThreadSanitizer (LLVM parts) + N: Michael Spencer E: bigcheesegs@gmail.com D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size @@ -126,10 +134,18 @@ E: thomas.stellard@amd.com E: mesa-dev@lists.freedesktop.org D: R600 Backend +N: Evgeniy Stepanov +E: eugenis@google.com +D: MemorySanitizer (LLVM part) + N: Andrew Trick E: atrick@apple.com D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling N: Bill Wendling -E: wendling@apple.com +E: isanbard@gmail.com D: libLTO, IR Linker + +N: Peter Zotov +E: whitequark@whitequark.org +D: OCaml bindings diff --git a/CREDITS.TXT b/CREDITS.TXT index 844ad39d03f17..3c1dcb07fc1fe 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -253,7 +253,8 @@ D: Release manager (1.7+) N: Sylvestre Ledru E: sylvestre@debian.org -W: http://sylvesre.ledru.info/ +W: http://sylvestre.ledru.info/ +W: http://llvm.org/apt/ D: Debian and Ubuntu packaging D: Continous integration with jenkins @@ -300,6 +301,7 @@ D: Added STI Cell SPU backend. N: Kai Nacke E: kai@redstar.de D: Support for implicit TLS model used with MS VC runtime +D: Dumping of Win64 EH structures N: Takumi Nakamura E: geek4civic@gmail.com @@ -364,7 +366,7 @@ I: arosenberg D: ARM calling conventions rewrite, hard float support N: Chad Rosier -E: mcrosier@apple.com +E: mcrosier@codeaurora.org D: ARM fast-isel improvements D: Performance monitoring @@ -410,6 +412,11 @@ E: rspencer@reidspencer.com W: http://reidspencer.com/ D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid +N: Alp Toker +E: alp@nuanti.com +W: http://atoker.com/ +D: C++ frontend next generation standards implementation + N: Craig Topper E: craig.topper@gmail.com D: X86 codegen and disassembler improvements. AVX2 support. @@ -428,10 +435,11 @@ D: ARM backend improvements D: Thread Local Storage implementation N: Bill Wendling -E: wendling@apple.com -D: Release manager +I: wendling +E: isanbard@gmail.com +D: Release manager, IR Linker, LTO D: Bunches of stuff N: Bob Wilson E: bob.wilson@acm.org -D: Advanced SIMD (NEON) support in the ARM backend +D: Advanced SIMD (NEON) support in the ARM backend. diff --git a/LICENSE.TXT b/LICENSE.TXT index aa7b11922ec06..66d6647ffd702 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -68,3 +68,4 @@ Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h diff --git a/LLVMBuild.txt b/LLVMBuild.txt index e763fd2afee2b..9cee3030a9355 100644 --- a/LLVMBuild.txt +++ b/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = bindings docs examples lib projects runtime tools utils +subdirectories = bindings docs examples lib projects tools utils [component_0] type = Group diff --git a/Makefile b/Makefile index 7a1b19045945f..e3672b76b4dd9 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ LEVEL := . # 3. Build IR, 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. +# 6. Build tools and docs. # # When cross-compiling, there are some things (tablegen) that need to # be build for the build system first. @@ -31,7 +31,7 @@ ifeq ($(BUILD_DIRS_ONLY),1) OPTIONAL_DIRS := tools/clang/utils/TableGen else DIRS := lib/Support lib/TableGen utils lib/IR lib tools/llvm-shlib \ - tools/llvm-config tools runtime docs unittests + tools/llvm-config tools docs unittests OPTIONAL_DIRS := projects bindings endif @@ -52,17 +52,17 @@ ifneq ($(ENABLE_DOCS),1) endif ifeq ($(MAKECMDGOALS),libs-only) - DIRS := $(filter-out tools runtime docs, $(DIRS)) + DIRS := $(filter-out tools docs, $(DIRS)) OPTIONAL_DIRS := endif ifeq ($(MAKECMDGOALS),install-libs) - DIRS := $(filter-out tools runtime docs, $(DIRS)) + DIRS := $(filter-out tools docs, $(DIRS)) OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) endif ifeq ($(MAKECMDGOALS),tools-only) - DIRS := $(filter-out runtime docs, $(DIRS)) + DIRS := $(filter-out docs, $(DIRS)) OPTIONAL_DIRS := endif @@ -72,7 +72,7 @@ ifeq ($(MAKECMDGOALS),install-clang) tools/clang/tools/c-index-test \ tools/clang/include/clang-c \ tools/clang/runtime tools/clang/docs \ - tools/lto runtime + tools/lto OPTIONAL_DIRS := NO_INSTALL = 1 endif @@ -84,7 +84,7 @@ ifeq ($(MAKECMDGOALS),clang-only) endif ifeq ($(MAKECMDGOALS),unittests) - DIRS := $(filter-out tools runtime docs, $(DIRS)) utils unittests + DIRS := $(filter-out tools docs, $(DIRS)) utils unittests OPTIONAL_DIRS := endif @@ -253,7 +253,7 @@ AWK = awk # a given path. svnup() requires one argument: the root to search from. define SUB_SVN_DIRS svnup() { - dirs=`svn status --no-ignore $$1 | awk '/I|\? / {print $$2}' | LC_ALL=C xargs svn info 2>/dev/null | awk '/^Path:\ / {print $$2}'`; + dirs=`svn status --no-ignore $$1 | awk '/^(I|\?) / {print $$2}' | LC_ALL=C xargs svn info 2>/dev/null | awk '/^Path:\ / {print $$2}'`; if [ "$$dirs" = "" ]; then return; fi; diff --git a/Makefile.config.in b/Makefile.config.in index fd4f6ef5d814c..dcca45f36cd87 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -235,6 +235,9 @@ ENABLE_LIBCPP = @ENABLE_LIBCPP@ # When ENABLE_CXX11 is enabled, LLVM uses c++11 mode by default to build. ENABLE_CXX11 = @ENABLE_CXX11@ +# When ENABLE_SPLIT_DWARF is enabled, LLVM uses -gfission to build in debug mode. +ENABLE_SPLIT_DWARF = @ENABLE_SPLIT_DWARF@ + # When ENABLE_CLANG_ARCMT is enabled, clang will have ARCMigrationTool. ENABLE_CLANG_ARCMT = @ENABLE_CLANG_ARCMT@ diff --git a/Makefile.rules b/Makefile.rules index f0c542b7f82cd..68f6cf8ec5d12 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -42,7 +42,7 @@ 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: .c .cpp .cc .h .hpp .o .a .td .ps .dot .m .mm .SUFFIXES: $(SHLIBEXT) $(SUFFIXES) #-------------------------------------------------------------------- @@ -274,11 +274,9 @@ 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) + ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin Darwin DragonFly FreeBSD GNU/kFreeBSD)) OmitFramePointer := -fomit-frame-pointer endif - endif CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) @@ -287,7 +285,6 @@ ifeq ($(ENABLE_OPTIMIZED),1) BuildMode := $(BuildMode)+Debug CXX.Flags += -g C.Flags += -g - LD.Flags += -g KEEP_SYMBOLS := 1 endif else @@ -295,13 +292,16 @@ else BuildMode := Unoptimized CXX.Flags += C.Flags += - LD.Flags += KEEP_SYMBOLS := 1 else BuildMode := Debug + ifeq ($(ENABLE_SPLIT_DWARF), 1) + CXX.Flags += -gsplit-dwarf + C.Flags += -gsplit-dwarf + else CXX.Flags += -g C.Flags += -g - LD.Flags += -g + endif KEEP_SYMBOLS := 1 endif endif @@ -324,7 +324,7 @@ 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 + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg KEEP_SYMBOLS := 1 endif @@ -496,27 +496,6 @@ ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) endif endif -#-------------------------------------------------------------------- -# LLVM Capable Compiler -#-------------------------------------------------------------------- - -ifneq ($(findstring llvm-gcc,$(LLVMCC_OPTION)),) - LLVMCC := $(LLVMGCC) - LLVMCXX := $(LLVMGXX) -else - ifneq ($(findstring clang,$(LLVMCC_OPTION)),) - 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 #-------------------------------------------------------------------- @@ -571,9 +550,9 @@ ifeq ($(HOST_OS),Darwin) DARWIN_VERSION := `sw_vers -productVersion` endif # Strip a number like 10.4.7 to 10.4 - DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]).*/\1/') + 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/') + DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]+).*/\1/') LoadableModuleOptions := -Wl,-flat_namespace -Wl,-undefined,suppress SharedLinkOptions := -dynamiclib @@ -629,32 +608,24 @@ ifndef KEEP_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)) + ifndef TOOL_NO_EXPORTS + LD.Flags += $(RDYNAMIC) + endif 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 + else + ifneq ($(DARWIN_MAJVERS),4) + LD.Flags += $(RPATH) -Wl,@executable_path/../lib + endif + ifeq ($(RC_XBS),YES) + TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX) + LD.Flags += -Wl,-object_path_lto -Wl,$(TempFile) endif endif -else - ifneq ($(DARWIN_MAJVERS),4) - LD.Flags += $(RPATH) -Wl,@executable_path/../lib - endif - ifeq ($(RC_XBS),YES) - TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX) - LD.Flags += -Wl,-object_path_lto -Wl,$(TempFile) - endif -endif endif @@ -696,9 +667,9 @@ ifdef UNIVERSAL UNIVERSAL_ARCH := i386 ppc endif UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %) - CompileCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) + TargetCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) ifdef UNIVERSAL_SDK_PATH - CompileCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) + TargetCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) endif # Building universal cannot compute dependencies automatically. @@ -760,17 +731,12 @@ Preprocess.CXX= $(Compile.Wrapper) \ $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ $(CompileCommonOpts) $(CXX.Flags) -E Link = $(Compile.Wrapper) \ - $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ - $(LDFLAGS) $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) + $(CXX) $(CXXFLAGS) $(LD.Flags) $(LDFLAGS) \ + $(TargetCommonOpts) $(Strip) -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 @@ -785,7 +751,6 @@ TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags) Archive = $(AR) $(AR.Flags) -LArchive = $(LLVMToolDir)/llvm-ar rcsf ifdef RANLIB Ranlib = $(RANLIB) else @@ -811,9 +776,10 @@ Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) endif BaseNameSources := $(sort $(basename $(Sources))) +SourceDirs := $(sort $(dir $(Sources))) ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) -ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) +ObjectDirs := $(SourceDirs:%=$(ObjDir)/%) #---------------------------------------------------------- # For Mingw MSYS bash and Python/w32: @@ -850,9 +816,18 @@ $(DESTDIR)$(PROJ_bindir) $(DESTDIR)$(PROJ_libdir) $(DESTDIR)$(PROJ_includedir) $ $(Verb) $(MKDIR) $* > /dev/null $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@ -.PRECIOUS: $(ObjDir)/.dir $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir .PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir +#--------------------------------------------------------- +# Collect the object directories (as there may be more +# than one if the source code is spread across +# subdirectories). +#--------------------------------------------------------- + +OBJECT_DIRS := $(ObjDir)/.dir $(ObjectDirs:%=%/.dir) +.PRECIOUS: $(OBJECT_DIRS) + #--------------------------------------------------------- # Handle the DIRS options for sequential construction #--------------------------------------------------------- @@ -1141,67 +1116,6 @@ 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 := $(LLVMLINK) - - -ifdef EXPORTED_SYMBOL_FILE -LinkModule += -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) -endif - -$(Module): $(BUILT_SOURCES) $(ObjectsBC) $(LibDir)/.dir $(LLVMLINK) - $(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 @@ -1217,7 +1131,6 @@ 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: @@ -1279,73 +1192,7 @@ $(DestSharedLib): $(LibName.SO) $(DestSharedLibDir) 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 = $(LLVMLINK) -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) - -$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir $(LLVMLINK) \ - $(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 + -$(Verb) $(RM) -f $(DestSharedLib) endif endif @@ -1454,7 +1301,7 @@ LD.Flags += -Wl,-exported_symbol,_main endif endif -ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux NetBSD FreeBSD GNU)) +ifeq ($(HOST_OS), $(filter $(HOST_OS), DragonFly Linux NetBSD FreeBSD GNU/kFreeBSD GNU)) ifneq ($(ARCH), Mips) LD.Flags += -Wl,--version-script=$(LLVM_SRC_ROOT)/autoconf/ExportMap.map endif @@ -1596,6 +1443,8 @@ ifeq ($(HOST_OS),HP-UX) DISABLE_AUTO_DEPENDENCIES=1 endif +COMPILE_DEPS = $(OBJECT_DIRS) $(BUILT_SOURCES) $(PROJ_MAKEFILE) + # Provide rule sets for when dependency generation is enabled ifndef DISABLE_AUTO_DEPENDENCIES @@ -1611,182 +1460,98 @@ DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ 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) +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) $(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) +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) $(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) +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) $(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) +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) $(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) +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) $(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) +$(ObjDir)/%.o: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.o: %.m $(COMPILE_DEPS) $(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) +$(BuildMode)/%.ii: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.ii: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.ii: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.ii: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" $(Verb) $(Preprocess.CXX) $< -o $@ -$(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.i: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" $(Verb) $(Preprocess.C) $< -o $@ -$(BuildMode)/%.i: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(BuildMode)/%.i: %.m $(COMPILE_DEPS) $(Echo) "Compiling $*.m for $(BuildMode) build to .i file" $(Verb) $(Preprocess.C) $< -o $@ -$(ObjDir)/%.s: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.cpp $(COMPILE_DEPS) $(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.mm $(COMPILE_DEPS) $(Echo) "Compiling $*.mm to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.cc $(COMPILE_DEPS) $(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.CXX) $< -o $@ -S -$(ObjDir)/%.s: %.c $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.c $(COMPILE_DEPS) $(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -S -$(ObjDir)/%.s: %.m $(ObjDir)/.dir $(BUILT_SOURCES) +$(ObjDir)/%.s: %.m $(COMPILE_DEPS) $(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 ############################################################################### @@ -1954,11 +1719,6 @@ ifndef IS_CLEANING_TARGET 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 diff --git a/autoconf/config.guess b/autoconf/config.guess index dd6dcb3d92a14..370da42dcad12 100755 --- a/autoconf/config.guess +++ b/autoconf/config.guess @@ -965,6 +965,9 @@ EOF ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-gnu + exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; diff --git a/autoconf/configure.ac b/autoconf/configure.ac index a5caac971b485..a9d491548f113 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -31,9 +31,9 @@ dnl=== dnl===-----------------------------------------------------------------------=== dnl Initialize autoconf and define the package name, version number and dnl address for reporting bugs. -AC_INIT([LLVM],[3.3],[http://llvm.org/bugs/]) +AC_INIT([LLVM],[3.4],[http://llvm.org/bugs/]) AC_DEFINE([LLVM_VERSION_MAJOR], [3], [Major version of the LLVM API]) -AC_DEFINE([LLVM_VERSION_MINOR], [3], [Minor version of the LLVM API]) +AC_DEFINE([LLVM_VERSION_MINOR], [4], [Minor version of the LLVM API]) dnl Provide a copyright substitution and ensure the copyright notice is included dnl in the output of --version option of the generated configure script. @@ -61,8 +61,8 @@ fi dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS, dnl instead of the autoconf default (for example, '-g -O2' for CC=gcc). -${CFLAGS=} -${CXXFLAGS=} +: ${CFLAGS=} +: ${CXXFLAGS=} dnl We need to check for the compiler up here to avoid anything else dnl starting with a different one. @@ -222,11 +222,16 @@ AC_CACHE_CHECK([type of operating system we're going to host on], llvm_cv_no_link_all_option="-Wl,-noall_load" llvm_cv_os_type="Minix" llvm_cv_platform_type="Unix" ;; - *-*-freebsd* | *-*-kfreebsd-gnu) + *-*-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" ;; + *-*-kfreebsd-gnu) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU/kFreeBSD" + llvm_cv_platform_type="Unix" ;; *-*-openbsd*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -317,8 +322,10 @@ AC_CACHE_CHECK([type of operating system we're going to target], llvm_cv_target_os_type="Darwin" ;; *-*-minix*) llvm_cv_target_os_type="Minix" ;; - *-*-freebsd* | *-*-kfreebsd-gnu) + *-*-freebsd*) llvm_cv_target_os_type="FreeBSD" ;; + *-*-kfreebsd-gnu) + llvm_cv_target_os_type="GNU/kFreeBSD" ;; *-*-openbsd*) llvm_cv_target_os_type="OpenBSD" ;; *-*-netbsd*) @@ -400,7 +407,6 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; hexagon-*) llvm_cv_target_arch="Hexagon" ;; - mblaze-*) llvm_cv_target_arch="MBlaze" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -435,7 +441,6 @@ case $host in xcore-*) host_arch="XCore" ;; msp430-*) host_arch="MSP430" ;; hexagon-*) host_arch="Hexagon" ;; - mblaze-*) host_arch="MBlaze" ;; s390x-*) host_arch="SystemZ" ;; *) host_arch="Unknown" ;; esac @@ -510,6 +515,19 @@ case "$enableval" in *) AC_MSG_ERROR([Invalid setting for --enable-cxx11. Use "yes" or "no"]) ;; esac +dnl --enable-fission : check whether or not to use -gsplit-dwarf on the command +dnl line +AC_ARG_ENABLE(split-dwarf, + AS_HELP_STRING([--enable-split-dwarf], + [Use split-dwarf if available (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_SPLIT_DWARF,[1]) ;; + no) AC_SUBST(ENABLE_SPLIT_DWARF,[0]) ;; + default) AC_SUBST(ENABLE_SPLIT_DWARF,[0]);; + *) AC_MSG_ERROR([Invalid setting for --enable-split-dwarf. Use "yes" or "no"]) ;; +esac + dnl --enable-clang-arcmt: check whether to enable clang arcmt clang_arcmt="yes" AC_ARG_ENABLE(clang-arcmt, @@ -533,7 +551,12 @@ AC_ARG_ENABLE(clang-static-analyzer, enableval="yes") case "$enableval" in yes) AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[1]) ;; - no) AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[0]) ;; + no) + if test ${clang_arcmt} != "no" ; then + AC_MSG_ERROR([Cannot enable clang ARC Migration Tool while disabling static analyzer.]) + fi + AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[0]) + ;; default) AC_SUBST(ENABLE_CLANG_STATIC_ANALYZER,[1]);; *) AC_MSG_ERROR([Invalid setting for --enable-clang-static-analyzer. Use "yes" or "no"]) ;; esac @@ -654,7 +677,6 @@ else XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; - MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;; NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;; SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; @@ -778,33 +800,50 @@ esac AC_DEFINE_UNQUOTED([ENABLE_TIMESTAMPS],$ENABLE_TIMESTAMPS, [Define if timestamp information (e.g., __DATE__) is allowed]) -dnl Enable embedding timestamp information into build. +dnl Enable support for showing backtraces. +AC_ARG_ENABLE(backtraces, AS_HELP_STRING( + [--enable-backtraces], + [Enable embedding backtraces on crash (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_backtraces="yes" ;; + no) llvm_cv_enable_backtraces="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-backtraces. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_backtraces="yes") +if test "$llvm_cv_enable_backtraces" = "yes" ; then + AC_DEFINE([ENABLE_BACKTRACES],[1], + [Define if you want backtraces on crash]) +fi -AC_ARG_ENABLE(backtraces, - AS_HELP_STRING([--enable-backtraces], - [Enable embedding backtraces on crash (default is YES)]),, - enableval=default) -case "$enableval" in - yes) AC_SUBST(ENABLE_BACKTRACES,[1]) ;; - no) AC_SUBST(ENABLE_BACKTRACES,[0]) ;; - default) AC_SUBST(ENABLE_BACKTRACES,[1]) ;; - *) AC_MSG_ERROR([Invalid setting for --enable-backtraces. Use "yes" or "no"]) ;; -esac -AC_DEFINE_UNQUOTED([ENABLE_BACKTRACES],$ENABLE_BACKTRACES, - [Define if you want backtraces on crash]) +dnl Enable installing platform specific signal handling overrides, for improved +dnl CrashRecovery support or interaction with crash reporting software. This +dnl support may be inappropriate for some clients embedding LLVM as a library. +AC_ARG_ENABLE(crash-overrides, AS_HELP_STRING( + [--enable-crash-overrides], + [Enable crash handling overrides (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_crash_overrides="yes" ;; + no) llvm_cv_enable_crash_overrides="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-crash-overrides. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_crash_overrides="yes") +if test "$llvm_cv_enable_crash_overrides" = "yes" ; then + AC_DEFINE([ENABLE_CRASH_OVERRIDES],[1], + [Define to enable crash handling overrides]) +fi 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, arm, aarch64, mips, hexagon, - xcore, msp430, nvptx, systemz, and cpp (default=all)]),, + xcore, msp430, nvptx, systemz, r600, 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 AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -821,9 +860,9 @@ case "$enableval" in msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; - mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + r600) TARGETS_TO_BUILD="R600 $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" ;; @@ -832,7 +871,6 @@ case "$enableval" in AArch64) TARGETS_TO_BUILD="AArch64 $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" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; @@ -1056,6 +1094,17 @@ AC_ARG_WITH(bug-report-url, AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval", [Bug report URL.]) +dnl --enable-terminfo: check whether the user wants to control use of terminfo: +AC_ARG_ENABLE(terminfo,AS_HELP_STRING( + [--enable-terminfo], + [Query the terminfo database if available (default is YES)]), + [case "$enableval" in + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-terminfo. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_terminfo="yes") + 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)]), @@ -1179,15 +1228,15 @@ if test "$DOTTY" != "echo dotty" ; then 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]) +AC_PATH_PROGS(XDOT, [xdot xdot.py], [echo xdot]) +if test "$XDOT" != "echo xdot" ; then + AC_DEFINE([HAVE_XDOT],[1],[Define if the xdot 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:\//' ` + XDOT=`echo $XDOT | 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]) + AC_DEFINE_UNQUOTED([LLVM_PATH_XDOT],"$XDOT${EXEEXT}", + [Define to path to xdot program if found or 'echo xdot' otherwise]) fi dnl Find the install program @@ -1223,7 +1272,7 @@ 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. +dnl Determine whether the compiler supports the -rdynamic option. AC_LINK_EXPORT_DYNAMIC dnl Determine whether the linker supports the --version-script option. @@ -1328,12 +1377,13 @@ else fi AC_MSG_CHECKING([for python >= 2.5]) -ac_python_version=`$PYTHON -c 'import sys; print sys.version.split()[[0]]'` +ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` -if test "$ac_python_version_major" -eq "2" \ - && test "$ac_python_version_minor" -ge "5" ; then +if test "$ac_python_version_major" -gt "2" || \ + (test "$ac_python_version_major" -eq "2" && \ + test "$ac_python_version_minor" -ge "5") ; then AC_MSG_RESULT([$PYTHON ($ac_python_version)]) else AC_MSG_RESULT([not found]) @@ -1350,6 +1400,7 @@ AC_CHECK_LIB(m,sin) if test "$llvm_cv_os_type" = "MingW" ; then AC_CHECK_LIB(imagehlp, main) AC_CHECK_LIB(psapi, main) + AC_CHECK_LIB(shell32, main) fi dnl dlopen() is required for plugin support. @@ -1362,6 +1413,14 @@ dnl macros to detect whether clock_gettime is available, this just finds the dnl right libraries to link with. AC_SEARCH_LIBS(clock_gettime,rt) +dnl The curses library is optional; used for querying terminal info +if test "$llvm_cv_enable_terminfo" = "yes" ; then + dnl We need the has_color functionality in curses for it to be useful. + AC_SEARCH_LIBS(setupterm,tinfo terminfo curses ncurses ncursesw, + AC_DEFINE([HAVE_TERMINFO],[1], + [Define if the setupterm() function is supported this platform.])) +fi + 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], @@ -1515,11 +1574,11 @@ AC_HEADER_TIME AC_LANG_PUSH([C++]) AC_CHECK_HEADERS([cxxabi.h]) AC_LANG_POP([C++]) -AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h]) +AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.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([utime.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([sys/ioctl.h malloc/malloc.h mach/mach.h]) AC_CHECK_HEADERS([valgrind/valgrind.h]) AC_CHECK_HEADERS([fenv.h]) AC_CHECK_DECLS([FE_ALL_EXCEPT, FE_INEXACT], [], [], [[#include ]]) @@ -1594,10 +1653,11 @@ AC_CHECK_FUNCS([powf fmodf strtof round ]) AC_CHECK_FUNCS([log log2 log10 exp exp2]) AC_CHECK_FUNCS([getpagesize getrusage getrlimit setrlimit gettimeofday ]) AC_CHECK_FUNCS([isatty mkdtemp mkstemp ]) -AC_CHECK_FUNCS([mktemp posix_spawn pread realpath sbrk setrlimit strdup ]) +AC_CHECK_FUNCS([mktemp posix_spawn pread realpath sbrk setrlimit ]) AC_CHECK_FUNCS([strerror strerror_r setenv arc4random ]) AC_CHECK_FUNCS([strtoll strtoq sysconf malloc_zone_statistics ]) AC_CHECK_FUNCS([setjmp longjmp sigsetjmp siglongjmp writev]) +AC_CHECK_FUNCS([futimes futimens]) AC_C_PRINTF_A AC_FUNC_RAND48 @@ -1736,7 +1796,6 @@ if test "${prefix}" = "NONE" ; then 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"; @@ -1746,7 +1805,6 @@ 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) @@ -1766,8 +1824,6 @@ 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", @@ -1827,7 +1883,7 @@ for a_binding in $BINDINGS_TO_BUILD ; do AC_SUBST(OCAML_LIBDIR,$ocaml_stdlib) else # ocaml stdlib is outside our prefix; use libdir/ocaml - AC_SUBST(OCAML_LIBDIR,$LLVM_LIBDIR/ocaml) + AC_SUBST(OCAML_LIBDIR,${prefix}/lib/ocaml) fi fi ;; @@ -1850,7 +1906,7 @@ AC_SUBST(RPATH) dnl Determine linker rdynamic flag if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then - RDYNAMIC="-Wl,-export-dynamic" + RDYNAMIC="-rdynamic" else RDYNAMIC="" fi @@ -1913,7 +1969,6 @@ 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) diff --git a/autoconf/m4/libtool.m4 b/autoconf/m4/libtool.m4 index 05af7a2ee3fec..385d00b468402 100644 --- a/autoconf/m4/libtool.m4 +++ b/autoconf/m4/libtool.m4 @@ -530,7 +530,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - ppc64-*linux*|powerpc64-*linux*) + ppc64-*linux*|powerpc64-*linux*|ppc64le-*linux*|powerpc64le-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) diff --git a/autoconf/m4/link_options.m4 b/autoconf/m4/link_options.m4 index 57da4a0d92699..b58d61745f970 100644 --- a/autoconf/m4/link_options.m4 +++ b/autoconf/m4/link_options.m4 @@ -40,23 +40,24 @@ if test "$llvm_cv_link_use_r" = yes ; then ]) # -# Determine if the system can handle the -R option being passed to the linker. +# Determine if the system can handle the -rdynamic option being passed +# to the compiler. # # This macro is specific to LLVM. # AC_DEFUN([AC_LINK_EXPORT_DYNAMIC], -[AC_CACHE_CHECK([for compiler -Wl,-export-dynamic option], +[AC_CACHE_CHECK([for compiler -rdynamic option], [llvm_cv_link_use_export_dynamic], [ AC_LANG_PUSH([C]) oldcflags="$CFLAGS" - CFLAGS="$CFLAGS -Wl,-export-dynamic" + CFLAGS="$CFLAGS -rdynamic" 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.]) + AC_DEFINE([HAVE_LINK_EXPORT_DYNAMIC],[1],[Define if you can use -rdynamic.]) fi ]) diff --git a/autoconf/m4/ltdl.m4 b/autoconf/m4/ltdl.m4 index 407a16e2d694b..b3302fa61c9e1 100644 --- a/autoconf/m4/ltdl.m4 +++ b/autoconf/m4/ltdl.m4 @@ -68,7 +68,6 @@ 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]) @@ -78,15 +77,9 @@ 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_HEADERS([errno.h malloc.h memory.h unistd.h]) +AC_CHECK_HEADERS([mach-o/dyld.h]) -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 @@ -206,20 +199,6 @@ if test -n "$libltdl_cv_shlibext"; then 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], diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index a89caefb4ded5..44562fe8db382 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -8,7 +8,8 @@ ##===----------------------------------------------------------------------===## LEVEL := ../.. -DIRS = llvm bitreader bitwriter analysis target executionengine transforms +DIRS = llvm bitreader bitwriter irreader analysis target executionengine \ + transforms linker backends ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml ocamldoc: diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index a2a8b02eac7d3..f8ed841d668ef 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -1,4 +1,4 @@ -##===- tools/ml/Makefile -----------------------------------*- Makefile -*-===## +##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -7,10 +7,10 @@ # ##===----------------------------------------------------------------------===## # -# An ocaml library is a unique project type in the context of LLVM, so rules are +# 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: +# Reference materials on installing OCaml libraries: # # https://fedoraproject.org/wiki/Packaging/OCaml # http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt @@ -23,6 +23,10 @@ include $(LEVEL)/Makefile.config CXX.Flags += -I"$(shell $(OCAMLC) -where)" C.Flags += -I"$(shell $(OCAMLC) -where)" +ifeq ($(ENABLE_SHARED),1) +LINK_COMPONENTS := all +endif + include $(LEVEL)/Makefile.common # Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the @@ -38,6 +42,18 @@ UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents)) endif endif +# How do we link OCaml executables with LLVM? +# 1) If this is a --enable-shared build, build stub libraries. This also allows +# to use LLVM from toplevels. +# 2) If this is a --disable-shared build, embed ocamlc options for building +# a custom runtime and a static executable. It is not possible to use LLVM +# from toplevels. +ifneq ($(ObjectsO),) +ifeq ($(ENABLE_SHARED),1) +OCAMLSTUBS := 1 +endif +endif + # Tools OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) ifndef IS_CLEANING_TARGET @@ -60,14 +76,36 @@ endif Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) + +ifdef OCAMLSTUBS +# Avoid the need for LD_LIBRARY_PATH +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) +OCAMLRPATH := $(RPATH) -Wl,'$(SharedLibDir)' +endif +endif +endif + +ifdef OCAMLSTUBS +Archive.CMA := $(strip $(OCAMLC) -a -dllib -l$(LIBRARYNAME) $(OCAMLDEBUGFLAG) \ + -o) +else Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ -o) +endif -Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +ifdef OCAMLSTUBS +Archive.CMXA := $(strip $(OCAMLOPT) -a $(patsubst %,-cclib %, \ + $(LLVMLibsOptions) -l$(LIBRARYNAME) \ + -L$(SharedLibDir) $(OCAMLRPATH)) \ + $(OCAMLDEBUGFLAG) -o) +else Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) +endif ifdef OCAMLOPT -Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) +Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamlLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) else Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) endif @@ -113,6 +151,10 @@ OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma) OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa) endif +ifdef OCAMLSTUBS +SharedLib := $(OcamlDir)/dll$(LIBRARYNAME)$(SHLIBEXT) +endif + ifdef TOOLNAME ifdef EXAMPLE_TOOL OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT) @@ -130,6 +172,10 @@ DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa endif +ifdef OCAMLSTUBS +DestSharedLib := $(PROJ_libocamldir)/dll$(LIBRARYNAME)$(SHLIBEXT) +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). @@ -187,6 +233,34 @@ uninstall-a:: endif +##===- Build stub library from C sources ----------------------------------===## + +ifdef SharedLib +all-local:: $(SharedLib) +clean-local:: clean-shared +install-local:: install-shared +uninstall-local:: uninstall-shared + +$(SharedLib): $(ObjectsO) $(OcamlDir)/.dir + $(Echo) "Building $(BuildMode) $(notdir $@)" + $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) $(LLVMLibsOptions) \ + -o $@ $(ObjectsO) + +clean-shared:: + -$(Verb) $(RM) -f $(SharedLib) + +install-shared:: $(SharedLib) + $(Echo) "Installing $(BuildMode) $(DestSharedLib)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(INSTALL) $(SharedLib) $(DestSharedLib) + $(Verb) + +uninstall-shared:: + $(Echo) "Uninstalling $(DestSharedLib)" + -$(Verb) $(RM) -f $(DestSharedLib) +endif + + ##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## all-local:: build-deplibs @@ -391,6 +465,7 @@ printcamlvars:: $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' $(Echo) "LibraryCMA : " '$(LibraryCMA)' $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' + $(Echo) "SharedLib : " '$(SharedLib)' $(Echo) "OcamlSources1: " '$(OcamlSources1)' $(Echo) "OcamlSources2: " '$(OcamlSources2)' $(Echo) "OcamlSources : " '$(OcamlSources)' @@ -404,6 +479,7 @@ printcamlvars:: $(Echo) "DestA : " '$(DestA)' $(Echo) "DestCMA : " '$(DestCMA)' $(Echo) "DestCMXA : " '$(DestCMXA)' + $(Echo) "DestSharedLib: " '$(DestSharedLib)' $(Echo) "UsedLibs : " '$(UsedLibs)' $(Echo) "UsedLibNames : " '$(UsedLibNames)' diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c index 97167055f70e6..91be2d3f6423b 100644 --- a/bindings/ocaml/analysis/analysis_ocaml.c +++ b/bindings/ocaml/analysis/analysis_ocaml.c @@ -1,4 +1,4 @@ -/*===-- analysis_ocaml.c - LLVM Ocaml Glue ----------------------*- C++ -*-===*\ +/*===-- analysis_ocaml.c - LLVM OCaml Glue ----------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| diff --git a/bindings/ocaml/analysis/llvm_analysis.ml b/bindings/ocaml/analysis/llvm_analysis.ml index fc4d20370747c..21088ab6ff413 100644 --- a/bindings/ocaml/analysis/llvm_analysis.ml +++ b/bindings/ocaml/analysis/llvm_analysis.ml @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.ml - LLVM Ocaml Interface -----------------*- C++ -*-===* +(*===-- llvm_analysis.ml - LLVM OCaml Interface -----------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/analysis/llvm_analysis.mli b/bindings/ocaml/analysis/llvm_analysis.mli index 793f482e3c6c7..1a0af02b38784 100644 --- a/bindings/ocaml/analysis/llvm_analysis.mli +++ b/bindings/ocaml/analysis/llvm_analysis.mli @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.mli - LLVM Ocaml Interface ----------------*- C++ -*-===* +(*===-- llvm_analysis.mli - LLVM OCaml Interface ----------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Intermediate representation analysis. - This interface provides an ocaml API for LLVM IR analyses, the classes in + 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 diff --git a/bindings/ocaml/backends/META.llvm_backend.in b/bindings/ocaml/backends/META.llvm_backend.in new file mode 100644 index 0000000000000..0d4a6d6846530 --- /dev/null +++ b/bindings/ocaml/backends/META.llvm_backend.in @@ -0,0 +1,8 @@ +name = "llvm_@TARGET@" +version = "@PACKAGE_VERSION@" +description = "@TARGET@ Backend for LLVM" +requires = "llvm" +archive(byte) = "llvm_@TARGET@.cma" +archive(native) = "llvm_@TARGET@.cmxa" +directory = "." +linkopts = "-ccopt -lstdc++" \ No newline at end of file diff --git a/bindings/ocaml/backends/Makefile b/bindings/ocaml/backends/Makefile new file mode 100644 index 0000000000000..ff39212c50bad --- /dev/null +++ b/bindings/ocaml/backends/Makefile @@ -0,0 +1,61 @@ +##===- bindings/ocaml/backends/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 master makefile for backend-specific bindings. It works by +# creating a stub makefile for each configured target, e.g. Makefile.ARM, and +# invoking it to compile the corresponding library, e.g. Llvm_ARM. +# +# This scheme allows to keep changes to Makefile.ocaml minimal. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.common + +include $(LEVEL)/Makefile.config +include $(LEVEL)/Makefile.common + +all-local:: all-backends +clean-local:: clean-backends +install-local:: install-backends +uninstall-local:: uninstall-backends + +stubs: + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(ECHO) "TARGET := $$i" > Makefile.$$i; \ + $(ECHO) "include Makefile.common" >> Makefile.$$i; \ + done + +all-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i all; \ + done + +clean-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i clean; \ + $(RM) -f Makefile.$$i; \ + done + +install-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i install; \ + done + +uninstall-backends: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i uninstall; \ + done + +ocamldoc: stubs + $(Verb) for i in $(TARGETS_TO_BUILD); do \ + $(MAKE) -f Makefile.$$i ocamldoc; \ + done + +.PHONY: all-backends clean-backends install-backends uninstall-backends ocamldoc diff --git a/bindings/ocaml/backends/Makefile.common b/bindings/ocaml/backends/Makefile.common new file mode 100644 index 0000000000000..be65dd0f861cd --- /dev/null +++ b/bindings/ocaml/backends/Makefile.common @@ -0,0 +1,65 @@ +##===- bindings/ocaml/backends/Makefile.common -------------*- 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 slave makefile for backend-specific bindings. This makefile should +# be included after defining TARGET. It will then substitute @TARGET@ for +# the value of TARGET in various *.in files and build an OCaml library in +# a regular way. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_$(TARGET) +UsedComponents := $(TARGET) +UsedOcamlInterfaces := llvm + +include $(LEVEL)/Makefile.config + +SOURCES := $(TARGET)_ocaml.c +OcamlHeaders1 := $(PROJ_SRC_DIR)/llvm_$(TARGET).mli +OcamlSources1 := $(PROJ_SRC_DIR)/llvm_$(TARGET).ml + +include ../Makefile.ocaml + +$(ObjDir)/llvm_$(TARGET).ml: $(PROJ_SRC_DIR)/llvm_backend.ml.in $(ObjDir)/.dir + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' $< > $@ + +$(ObjDir)/llvm_$(TARGET).mli: $(PROJ_SRC_DIR)/llvm_backend.mli.in $(ObjDir)/.dir + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' $< > $@ + +$(ObjDir)/$(TARGET)_ocaml.o: $(PROJ_SRC_DIR)/backend_ocaml.c $(ObjDir)/.dir + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) $(Compile.C) -DTARGET=$(TARGET) $< -o $@ + + +##===- OCamlFind Package --------------------------------------------------===## + +all-local:: copy-meta +install-local:: install-meta +uninstall-local:: uninstall-meta + +DestMETA := $(PROJ_libocamldir)/META.llvm_$(TARGET) + +# Easy way of generating META in the objdir +copy-meta: $(OcamlDir)/META.llvm_$(TARGET) + +$(OcamlDir)/META.llvm_$(TARGET): META.llvm_backend.in + $(Verb) $(SED) -e 's/@TARGET@/$(TARGET)/' \ + -e 's/@PACKAGE_VERSION@/$(LLVMVersion)/' $< > $@ + +install-meta:: $(OcamlDir)/META.llvm_$(TARGET) + $(Echo) "Install $(BuildMode) $(DestMETA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(DataInstall) $< "$(DestMETA)" + +uninstall-meta:: + $(Echo) "Uninstalling $(DestMETA)" + -$(Verb) $(RM) -f "$(DestMETA)" + +.PHONY: copy-meta install-meta uninstall-meta diff --git a/bindings/ocaml/backends/backend_ocaml.c b/bindings/ocaml/backends/backend_ocaml.c new file mode 100644 index 0000000000000..2d4ba852fda5c --- /dev/null +++ b/bindings/ocaml/backends/backend_ocaml.c @@ -0,0 +1,37 @@ +/*===-- backend_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" +#include "caml/memory.h" + +// TODO: Figure out how to call these only for targets which support them. +// LLVMInitialize ## target ## AsmPrinter(); +// LLVMInitialize ## target ## AsmParser(); +// LLVMInitialize ## target ## Disassembler(); + +#define INITIALIZER1(target) \ + CAMLprim value llvm_initialize_ ## target(value Unit) { \ + LLVMInitialize ## target ## TargetInfo(); \ + LLVMInitialize ## target ## Target(); \ + LLVMInitialize ## target ## TargetMC(); \ + return Val_unit; \ + } + +#define INITIALIZER(target) INITIALIZER1(target) + +INITIALIZER(TARGET) diff --git a/bindings/ocaml/backends/llvm_backend.ml.in b/bindings/ocaml/backends/llvm_backend.ml.in new file mode 100644 index 0000000000000..bd1e5860aa2d8 --- /dev/null +++ b/bindings/ocaml/backends/llvm_backend.ml.in @@ -0,0 +1,10 @@ +(*===-- llvm_backend.ml.in - 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 initialize : unit -> unit = "llvm_initialize_@TARGET@" diff --git a/bindings/ocaml/backends/llvm_backend.mli.in b/bindings/ocaml/backends/llvm_backend.mli.in new file mode 100644 index 0000000000000..9506789a7fddc --- /dev/null +++ b/bindings/ocaml/backends/llvm_backend.mli.in @@ -0,0 +1,19 @@ +(*===-- llvm_backend.mli.in - 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@ Initialization. + + This interface provides an OCaml API for initialization of + the @TARGET@ LLVM target. By referencing this module, you will cause + OCaml to load or link in the LLVM libraries corresponding to the target. + By calling [initialize], you will register components of this target + in the target registry, which is necessary in order to emit assembly, + object files, and so on. *) + +external initialize : unit -> unit = "llvm_initialize_@TARGET@" \ No newline at end of file diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c index ef72ce213d8b9..0264e73117da4 100644 --- a/bindings/ocaml/bitreader/bitreader_ocaml.c +++ b/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -1,4 +1,4 @@ -/*===-- bitwriter_ocaml.c - LLVM Ocaml Glue ---------------------*- C++ -*-===*\ +/*===-- bitwriter_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| |* are by and large transparent wrappers to the corresponding C functions. *| |* *| \*===----------------------------------------------------------------------===*/ diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml index 8b9d01d8fb010..865208c1ec0af 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.ml +++ b/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.ml - LLVM Ocaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitreader.ml - LLVM OCaml Interface ----------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli index 573de5e983055..ff377b9bc997f 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.mli +++ b/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.mli - LLVM Ocaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitreader.mli - LLVM OCaml Interface ---------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Bitcode reader. - This interface provides an ocaml API for the LLVM bitcode reader, the + This interface provides an OCaml API for the LLVM bitcode reader, the classes in the Bitreader library. *) exception Error of string diff --git a/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/bindings/ocaml/bitwriter/bitwriter_ocaml.c index 53c93cbdfe9bf..a47f7003e7ef1 100644 --- a/bindings/ocaml/bitwriter/bitwriter_ocaml.c +++ b/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -1,4 +1,4 @@ -/*===-- bitwriter_ocaml.c - LLVM Ocaml Glue ---------------------*- C++ -*-===*\ +/*===-- bitwriter_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/bindings/ocaml/bitwriter/llvm_bitwriter.ml index 3e69a3cc8fbba..fac85538dbab9 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.ml +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.ml - LLVM Ocaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitwriter.ml - LLVM OCaml Interface ----------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -7,7 +7,7 @@ * *===----------------------------------------------------------------------=== * - * This interface provides an ocaml API for the LLVM intermediate + * This interface provides an OCaml API for the LLVM intermediate * representation, the classes in the VMCore library. * *===----------------------------------------------------------------------===*) diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/bindings/ocaml/bitwriter/llvm_bitwriter.mli index ea9a87600a758..bb3e3b8945600 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.mli +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.mli - LLVM Ocaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitwriter.mli - LLVM OCaml Interface ---------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Bitcode writer. - This interface provides an ocaml API for the LLVM bitcode writer, the + 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 diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c index 02e030605720e..4b44a91066fe6 100644 --- a/bindings/ocaml/executionengine/executionengine_ocaml.c +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -1,4 +1,4 @@ -/*===-- executionengine_ocaml.c - LLVM Ocaml Glue ---------------*- C++ -*-===*\ +/*===-- executionengine_ocaml.c - LLVM OCaml Glue ---------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| @@ -324,3 +324,18 @@ CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F, return Val_unit; } +extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData); + +/* ExecutionEngine.t -> Llvm_target.DataLayout.t */ +CAMLprim value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { + value DataLayout; + LLVMTargetDataRef OrigDataLayout; + OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); + + char* TargetDataCStr; + TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); + DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); + LLVMDisposeMessage(TargetDataCStr); + + return DataLayout; +} diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index ddb53bbb5afd3..a738df765dce4 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.ml - LLVM Ocaml Interface ----------*- C++ -*-===* +(*===-- llvm_executionengine.ml - LLVM OCaml Interface ----------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -83,12 +83,11 @@ module ExecutionEngine = struct external free_machine_code: Llvm.llvalue -> t -> unit = "llvm_ee_free_machine_code" - external target_data: t -> Llvm_target.DataLayout.t - = "LLVMGetExecutionEngineTargetData" + external data_layout : t -> Llvm_target.DataLayout.t + = "llvm_ee_get_data_layout" (* 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 diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli index 0b06078bad860..16f08930a75b9 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.mli +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.mli - LLVM Ocaml Interface ---------*- C++ -*-===* +(*===-- llvm_executionengine.mli - LLVM OCaml Interface ---------*- C++ -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** JIT Interpreter. - This interface provides an ocaml API for LLVM execution engine (JIT/ + This interface provides an OCaml API for LLVM execution engine (JIT/ interpreter), the classes in the ExecutionEngine library. *) exception Error of string @@ -43,7 +43,6 @@ module GenericValue: sig 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 @@ -110,7 +109,7 @@ module ExecutionEngine: sig (** [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 @@ -119,19 +118,16 @@ module ExecutionEngine: sig [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 @@ -147,17 +143,12 @@ module ExecutionEngine: sig 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.DataLayout.t - + (** [data_layout ee] is the data layout of the execution engine [ee]. *) + val data_layout : t -> Llvm_target.DataLayout.t end val initialize_native_target : unit -> bool - diff --git a/bindings/ocaml/irreader/Makefile b/bindings/ocaml/irreader/Makefile new file mode 100644 index 0000000000000..7665999bb76ba --- /dev/null +++ b/bindings/ocaml/irreader/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/irreader/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_irreader interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_irreader +UsedComponents := irreader +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/irreader/irreader_ocaml.c b/bindings/ocaml/irreader/irreader_ocaml.c new file mode 100644 index 0000000000000..30c10c7b8b0ac --- /dev/null +++ b/bindings/ocaml/irreader/irreader_ocaml.c @@ -0,0 +1,59 @@ +/*===-- irreader_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/IRReader.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_irreader_error_exn; + +CAMLprim value llvm_register_irreader_exns(value Error) { + llvm_irreader_error_exn = Field(Error, 0); + register_global_root(&llvm_irreader_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_parse_ir(LLVMContextRef C, + LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + LLVMModuleRef M; + char *Message; + + if (LLVMParseIRInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_irreader_error_exn, Message); + + CAMLreturn((value) M); +} diff --git a/bindings/ocaml/irreader/llvm_irreader.ml b/bindings/ocaml/irreader/llvm_irreader.ml new file mode 100644 index 0000000000000..455b1fae032e7 --- /dev/null +++ b/bindings/ocaml/irreader/llvm_irreader.ml @@ -0,0 +1,17 @@ +(*===-- llvm_irreader.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. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_irreader_exns" +let _ = register_exns (Error "") + +external parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_ir" diff --git a/bindings/ocaml/irreader/llvm_irreader.mli b/bindings/ocaml/irreader/llvm_irreader.mli new file mode 100644 index 0000000000000..2b1147373b5c6 --- /dev/null +++ b/bindings/ocaml/irreader/llvm_irreader.mli @@ -0,0 +1,21 @@ +(*===-- llvm_irreader.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. + * + *===----------------------------------------------------------------------===*) + +(** IR reader. + + This interface provides an OCaml API for the LLVM assembly reader, the + classes in the IRReader library. *) + +exception Error of string + +(** [parse_ir context mb] parses the IR 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::ParseIR]. *) +val parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule diff --git a/bindings/ocaml/linker/Makefile b/bindings/ocaml/linker/Makefile new file mode 100644 index 0000000000000..ca1c96c9634e8 --- /dev/null +++ b/bindings/ocaml/linker/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/linker/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_linker +UsedComponents := linker +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/bindings/ocaml/linker/linker_ocaml.c b/bindings/ocaml/linker/linker_ocaml.c new file mode 100644 index 0000000000000..2491e3b8fa4ac --- /dev/null +++ b/bindings/ocaml/linker/linker_ocaml.c @@ -0,0 +1,54 @@ +/*===-- linker_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/Linker.h" +#include "caml/alloc.h" +#include "caml/memory.h" +#include "caml/fail.h" + +static value llvm_linker_error_exn; + +CAMLprim value llvm_register_linker_exns(value Error) { + llvm_linker_error_exn = Field(Error, 0); + register_global_root(&llvm_linker_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 +} + +/* llmodule -> llmodule -> Mode.t -> unit + raises Error msg on error */ +CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) { + char* Message; + + if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message)) + llvm_raise(llvm_linker_error_exn, Message); + + return Val_unit; +} diff --git a/bindings/ocaml/linker/llvm_linker.ml b/bindings/ocaml/linker/llvm_linker.ml new file mode 100644 index 0000000000000..2b73e2e9c4e90 --- /dev/null +++ b/bindings/ocaml/linker/llvm_linker.ml @@ -0,0 +1,22 @@ +(*===-- llvm_linker.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. + * + *===----------------------------------------------------------------------===*) + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_linker_exns" +let _ = register_exns (Error "") + +module Mode = struct + type t = + | DestroySource + | PreserveSource +end + +external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit + = "llvm_link_modules" \ No newline at end of file diff --git a/bindings/ocaml/linker/llvm_linker.mli b/bindings/ocaml/linker/llvm_linker.mli new file mode 100644 index 0000000000000..4def7a8cc9839 --- /dev/null +++ b/bindings/ocaml/linker/llvm_linker.mli @@ -0,0 +1,26 @@ +(*===-- llvm_linker.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. + * + *===----------------------------------------------------------------------===*) + +(** Linker. + + This interface provides an OCaml API for LLVM bitcode linker, + the classes in the Linker library. *) + +exception Error of string + +(** Linking mode. *) +module Mode : sig + type t = + | DestroySource + | PreserveSource +end + +(** [link_modules dst src mode] links [src] into [dst], raising [Error] + if the linking fails. *) +val link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit \ No newline at end of file diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in index fdb3253823733..c241ea514cbcf 100644 --- a/bindings/ocaml/llvm/META.llvm.in +++ b/bindings/ocaml/llvm/META.llvm.in @@ -46,6 +46,14 @@ package "ipo" ( archive(native) = "llvm_ipo.cmxa" ) +package "irreader" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "IR assembly reader for LLVM" + archive(byte) = "llvm_irreader.cma" + archive(native) = "llvm_irreader.cmxa" +) + package "scalar_opts" ( requires = "llvm" version = "@PACKAGE_VERSION@" @@ -54,6 +62,22 @@ package "scalar_opts" ( archive(native) = "llvm_scalar_opts.cmxa" ) +package "vectorize" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Vector Transforms for LLVM" + archive(byte) = "llvm_vectorize.cma" + archive(native) = "llvm_vectorize.cmxa" +) + +package "passmgr_builder" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Pass Manager Builder for LLVM" + archive(byte) = "llvm_passmgr_builder.cma" + archive(native) = "llvm_passmgr_builder.cmxa" +) + package "target" ( requires = "llvm" version = "@PACKAGE_VERSION@" @@ -61,3 +85,11 @@ package "target" ( archive(byte) = "llvm_target.cma" archive(native) = "llvm_target.cmxa" ) + +package "linker" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Intermediate Representation Linker for LLVM" + archive(byte) = "llvm_linker.cma" + archive(native) = "llvm_linker.cmxa" +) diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile index 203075a9bddeb..850f564a0c223 100644 --- a/bindings/ocaml/llvm/Makefile +++ b/bindings/ocaml/llvm/Makefile @@ -14,7 +14,7 @@ LEVEL := ../../.. LIBRARYNAME := llvm UsedComponents := core -UsedOcamLibs := llvm +UsedOcamlLibs := llvm include ../Makefile.ocaml diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index b169b85bc99f9..d36f360bf65f9 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -34,6 +34,7 @@ module TypeKind = struct | Pointer | Vector | Metadata + | X86_mmx end module Linkage = struct @@ -42,6 +43,7 @@ module Linkage = struct | Available_externally | Link_once | Link_once_odr + | Link_once_odr_auto_hide | Weak | Weak_odr | Appending @@ -53,6 +55,7 @@ module Linkage = struct | Ghost | Common | Linker_private + | Linker_private_weak end module Visibility = struct @@ -202,7 +205,48 @@ module Opcode = struct | AtomicRMW | Resume | LandingPad - | Unwind +end + +module LandingPadClauseTy = struct + type t = + | Catch + | Filter +end + +module ThreadLocalMode = struct + type t = + | None + | GeneralDynamic + | LocalDynamic + | InitialExec + | LocalExec +end + +module AtomicOrdering = struct + type t = + | NotAtomic + | Unordered + | Monotonic + | Invalid + | Acquire + | Release + | AcqiureRelease + | SequentiallyConsistent +end + +module AtomicRMWBinOp = struct + type t = + | Xchg + | Add + | Sub + | And + | Nand + | Or + | Xor + | Max + | Min + | UMax + | UMin end module ValueKind = struct @@ -216,6 +260,8 @@ module ValueKind = struct | BlockAddress | ConstantAggregateZero | ConstantArray + | ConstantDataArray + | ConstantDataVector | ConstantExpr | ConstantFP | ConstantInt @@ -234,6 +280,13 @@ exception IoError of string external register_exns : exn -> unit = "llvm_register_core_exns" let _ = register_exns (IoError "") +external install_fatal_error_handler : (string -> unit) -> unit + = "llvm_install_fatal_error_handler" +external reset_fatal_error_handler : unit -> unit + = "llvm_reset_fatal_error_handler" +external enable_pretty_stacktrace : unit -> unit + = "llvm_enable_pretty_stacktrace" + type ('a, 'b) llpos = | At_end of 'a | Before of 'b @@ -260,6 +313,8 @@ external data_layout: llmodule -> string external set_data_layout: string -> llmodule -> unit = "llvm_set_data_layout" external dump_module : llmodule -> unit = "llvm_dump_module" +external print_module : string -> llmodule -> unit = "llvm_print_module" +external string_of_llmodule : llmodule -> string = "llvm_string_of_llmodule" external set_module_inline_asm : llmodule -> string -> unit = "llvm_set_module_inline_asm" external module_context : llmodule -> llcontext = "LLVMGetModuleContext" @@ -268,6 +323,8 @@ external module_context : llmodule -> llcontext = "LLVMGetModuleContext" external classify_type : lltype -> TypeKind.t = "llvm_classify_type" external type_context : lltype -> llcontext = "llvm_type_context" external type_is_sized : lltype -> bool = "llvm_type_is_sized" +external dump_type : lltype -> unit = "llvm_dump_type" +external string_of_lltype : lltype -> string = "llvm_string_of_lltype" (*--... Operations on integer types ........................................--*) external i1_type : llcontext -> lltype = "llvm_i1_type" @@ -323,6 +380,7 @@ external vector_size : lltype -> int = "llvm_vector_size" (*--... Operations on other types ..........................................--*) external void_type : llcontext -> lltype = "llvm_void_type" external label_type : llcontext -> lltype = "llvm_label_type" +external x86_mmx_type : llcontext -> lltype = "llvm_x86_mmx_type" external type_by_name : llmodule -> string -> lltype option = "llvm_type_by_name" external classify_value : llvalue -> ValueKind.t = "llvm_classify_value" @@ -331,8 +389,9 @@ 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 string_of_llvalue : llvalue -> string = "llvm_string_of_llvalue" external replace_all_uses_with : llvalue -> llvalue -> unit - = "LLVMReplaceAllUsesWith" + = "llvm_replace_all_uses_with" (*--... Operations on uses .................................................--*) external use_begin : llvalue -> lluse option = "llvm_use_begin" @@ -391,7 +450,10 @@ external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata" external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" external get_mdstring : llvalue -> string option = "llvm_get_mdstring" -external get_named_metadata : llmodule -> string -> llvalue array = "llvm_get_namedmd" +external get_named_metadata : llmodule -> string -> llvalue array + = "llvm_get_namedmd" +external add_named_metadata_operand : llmodule -> string -> llvalue -> unit + = "llvm_append_namedmd" (*--... Operations on scalar constants .....................................--*) external const_int : lltype -> int -> llvalue = "llvm_const_int" @@ -477,7 +539,8 @@ 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_intcast : llvalue -> lltype -> is_signed:bool -> llvalue + = "llvm_const_intcast" external const_fpcast : llvalue -> lltype -> llvalue = "LLVMConstFPCast" external const_select : llvalue -> llvalue -> llvalue -> llvalue = "LLVMConstSelect" @@ -530,6 +593,14 @@ 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 thread_local_mode : llvalue -> ThreadLocalMode.t + = "llvm_thread_local_mode" +external set_thread_local_mode : ThreadLocalMode.t -> llvalue -> unit + = "llvm_set_thread_local_mode" +external is_externally_initialized : llvalue -> bool + = "llvm_is_externally_initialized" +external set_externally_initialized : bool -> llvalue -> unit + = "llvm_set_externally_initialized" external global_begin : llmodule -> (llmodule, llvalue) llpos = "llvm_global_begin" external global_succ : llvalue -> (llmodule, llvalue) llpos @@ -725,6 +796,10 @@ let unpack_attr (a : int32) : Attribute.t list = let add_function_attr llval attr = llvm_add_function_attr llval (pack_attr attr) +external add_target_dependent_function_attr + : llvalue -> string -> string -> unit + = "llvm_add_target_dependent_function_attr" + let remove_function_attr llval attr = llvm_remove_function_attr llval (pack_attr attr) @@ -803,6 +878,11 @@ 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 remove_block : llbasicblock -> unit = "llvm_remove_block" +external move_block_before : llbasicblock -> llbasicblock -> unit + = "llvm_move_block_before" +external move_block_after : llbasicblock -> llbasicblock -> unit + = "llvm_move_block_after" external append_block : llcontext -> string -> llvalue -> llbasicblock = "llvm_append_block" external insert_block : llcontext -> string -> llbasicblock -> llbasicblock @@ -872,8 +952,6 @@ external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode" external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate" -external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate" - let rec iter_instrs_range f i e = if i = e then () else match i with @@ -936,6 +1014,10 @@ let remove_instruction_param_attr llval i attr = external is_tail_call : llvalue -> bool = "llvm_is_tail_call" external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call" +(*--... Operations on load/store instructions (only) .......................--*) +external is_volatile : llvalue -> bool = "llvm_is_volatile" +external set_volatile : bool -> llvalue -> unit = "llvm_set_volatile" + (*--... Operations on phi nodes ............................................--*) external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit = "llvm_add_incoming" @@ -1078,6 +1160,11 @@ external build_load : llvalue -> string -> llbuilder -> llvalue = "llvm_build_load" external build_store : llvalue -> llvalue -> llbuilder -> llvalue = "llvm_build_store" +external build_atomicrmw : AtomicRMWBinOp.t -> llvalue -> llvalue -> + AtomicOrdering.t -> bool -> string -> llbuilder -> + llvalue + = "llvm_build_atomicrmw_bytecode" + "llvm_build_atomicrmw_native" external build_gep : llvalue -> llvalue array -> string -> llbuilder -> llvalue = "llvm_build_gep" external build_in_bounds_gep : llvalue -> llvalue array -> string -> @@ -1167,6 +1254,9 @@ external build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue module MemoryBuffer = struct external of_file : string -> llmemorybuffer = "llvm_memorybuffer_of_file" external of_stdin : unit -> llmemorybuffer = "llvm_memorybuffer_of_stdin" + external of_string : ?name:string -> string -> llmemorybuffer + = "llvm_memorybuffer_of_string" + external as_string : llmemorybuffer -> string = "llvm_memorybuffer_as_string" external dispose : llmemorybuffer -> unit = "llvm_memorybuffer_dispose" end @@ -1187,54 +1277,3 @@ module PassManager = struct 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 -> - (let ety = element_type ty in - match classify_type ety with - | TypeKind.Struct -> - (match struct_name ety with - | None -> (string_of_lltype ety) - | Some s -> s) ^ "*" - | _ -> (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.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.Half -> "half" - | TypeKind.Void -> "void" - | TypeKind.Metadata -> "metadata" diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index eb6c88355afbd..e996121793455 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -1,4 +1,4 @@ -(*===-- llvm/llvm.mli - LLVM Ocaml Interface -------------------------------===* +(*===-- llvm/llvm.mli - LLVM OCaml Interface ------------------------------===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Core API. - This interface provides an ocaml API for the LLVM intermediate + This interface provides an OCaml API for the LLVM intermediate representation, the classes in the VMCore library. *) @@ -67,6 +67,7 @@ module TypeKind : sig | Pointer | Vector | Metadata + | X86_mmx end (** The linkage of a global value, accessed with {!linkage} and @@ -77,6 +78,7 @@ module Linkage : sig | Available_externally | Link_once | Link_once_odr + | Link_once_odr_auto_hide | Weak | Weak_odr | Appending @@ -88,6 +90,7 @@ module Linkage : sig | Ghost | Common | Linker_private + | Linker_private_weak end (** The linker visibility of a global value, accessed with {!visibility} and @@ -115,6 +118,8 @@ module CallConv : sig convention from C. *) end +(** The attribute kind of a function parameter, result or the function itself. + See [llvm::Attribute::AttrKind]. *) module Attribute : sig type t = | Zext @@ -252,11 +257,61 @@ module Opcode : sig | AtomicRMW | Resume | LandingPad - | Unwind +end + +(** The type of a clause of a [landingpad] instruction. + See [llvm::LandingPadInst::ClauseType]. *) +module LandingPadClauseTy : sig + type t = + | Catch + | Filter +end + +(** The thread local mode of a global value, accessed with {!thread_local_mode} + and {!set_thread_local_mode}. + See [llvm::GlobalVariable::ThreadLocalMode]. *) +module ThreadLocalMode : sig + type t = + | None + | GeneralDynamic + | LocalDynamic + | InitialExec + | LocalExec +end + +(** The ordering of an atomic [load], [store], [cmpxchg], [atomicrmw] or + [fence] instruction. See [llvm::AtomicOrdering]. *) +module AtomicOrdering : sig + type t = + | NotAtomic + | Unordered + | Monotonic + | Invalid (* removed due to API changes *) + | Acquire + | Release + | AcqiureRelease + | SequentiallyConsistent +end + +(** The opcode of an [atomicrmw] instruction. + See [llvm::AtomicRMWInst::BinOp]. *) +module AtomicRMWBinOp : sig + type t = + | Xchg + | Add + | Sub + | And + | Nand + | Or + | Xor + | Max + | Min + | UMax + | UMin end (** The kind of an [llvalue], the result of [classify_value v]. - * See the various [LLVMIsA*] functions. *) + See the various [LLVMIsA*] functions. *) module ValueKind : sig type t = | NullValue @@ -268,6 +323,8 @@ module ValueKind : sig | BlockAddress | ConstantAggregateZero | ConstantArray + | ConstantDataArray + | ConstantDataVector | ConstantExpr | ConstantFP | ConstantInt @@ -281,6 +338,7 @@ module ValueKind : sig | Instruction of Opcode.t end + (** {6 Iteration} *) (** [Before b] and [At_end a] specify positions from the start of the ['b] list @@ -303,6 +361,21 @@ type ('a, 'b) llrev_pos = exception IoError of string +(** {6 Global configuration} *) + +(** [enable_pretty_stacktraces ()] enables LLVM's built-in stack trace code. + This intercepts the OS's crash signals and prints which component of LLVM + you were in at the time of the crash. *) +val enable_pretty_stacktrace : unit -> unit + +(** [install_fatal_error_handler f] installs [f] as LLVM's fatal error handler. + The handler will receive the reason for termination as a string. After + the handler has been executed, LLVM calls [exit(1)]. *) +val install_fatal_error_handler : (string -> unit) -> unit + +(** [reset_fatal_error_handler ()] resets LLVM's fatal error handler. *) +val reset_fatal_error_handler : unit -> unit + (** {6 Contexts} *) (** [create_context ()] creates a context for storing the "global" state in @@ -340,18 +413,15 @@ val dispose_module : llmodule -> unit [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 @@ -360,14 +430,23 @@ val set_data_layout: string -> llmodule -> unit error. See the method [llvm::Module::dump]. *) val dump_module : llmodule -> unit +(** [print_module f m] prints the .ll representation of the module [m] + to file [f]. See the method [llvm::Module::print]. *) +val print_module : string -> llmodule -> unit + +(** [string_of_llmodule m] returns the .ll representation of the module [m] + as a string. See the method [llvm::Module::print]. *) +val string_of_llmodule : llmodule -> string + (** [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 (** [module_context m] returns the context of the specified module. - * See the method [llvm::Module::getContext] *) + See the method [llvm::Module::getContext] *) val module_context : llmodule -> llcontext + (** {6 Types} *) (** [classify_type ty] returns the {!TypeKind.t} corresponding to the type [ty]. @@ -375,17 +454,22 @@ val module_context : llmodule -> llcontext val classify_type : lltype -> TypeKind.t (** [type_is_sized ty] returns whether the type has a size or not. - * If it doesn't then it is not safe to call the [DataLayout::] methods on it. - * *) + If it doesn't then it is not safe to call the [DataLayout::] methods on it. + *) val type_is_sized : lltype -> bool (** [type_context ty] returns the {!llcontext} corresponding to the type [ty]. See the method [llvm::Type::getContext]. *) val type_context : lltype -> llcontext +(** [dump_type ty] prints the .ll representation of the type [ty] to standard + error. See the method [llvm::Type::dump]. *) +val dump_type : lltype -> unit + (** [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 @@ -453,7 +537,6 @@ val function_type : lltype -> lltype array -> lltype 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 @@ -474,31 +557,29 @@ val param_types : lltype -> lltype array [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_name ty] returns the name of the named structure type [ty], - * or None if the structure type is not named *) + or None if the structure type is not named *) val struct_name : lltype -> string option (** [named_struct_type context name] returns the named structure type [name] - * in the context [context]. - * See the method [llvm::StructType::get]. *) + in the context [context]. + See the method [llvm::StructType::get]. *) val named_struct_type : llcontext -> string -> lltype (** [struct_set_body ty elts ispacked] sets the body of the named struct [ty] - * to the [elts] elements. - * See the moethd [llvm::StructType::setBody]. *) + to the [elts] elements. + See the moethd [llvm::StructType::setBody]. *) val struct_set_body : lltype -> lltype array -> bool -> unit (** [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 @@ -507,6 +588,7 @@ val is_packed : lltype -> bool [false] otherwise. See the method [llvm::StructType::isOpaque]. *) val is_opaque : lltype -> bool + (** {7 Operations on pointer, vector, and array types} *) (** [array_type ty n] returns the array type containing [n] elements of type @@ -523,7 +605,6 @@ val pointer_type : lltype -> lltype 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 @@ -555,17 +636,23 @@ val void_type : llcontext -> lltype [llvm::Type::LabelTy]. *) val label_type : llcontext -> lltype +(** [x86_mmx_type c] returns the x86 64-bit MMX register type in the + context [c]. See [llvm::Type::X86_MMXTy]. *) +val x86_mmx_type : llcontext -> lltype + (** [type_by_name m name] returns the specified type from the current module - * if it exists. - * See the method [llvm::Module::getTypeByName] *) + if it exists. + See the method [llvm::Module::getTypeByName] *) val type_by_name : llmodule -> string -> lltype option + (* {6 Values} *) (** [type_of v] returns the type of the value [v]. See the method [llvm::Value::getType]. *) val type_of : llvalue -> lltype +(** [classify_value v] returns the kind of the value [v]. *) val classify_value : llvalue -> ValueKind.t (** [value_name v] returns the name of the value [v]. For global values, this is @@ -582,12 +669,14 @@ val set_value_name : string -> llvalue -> unit error. See the method [llvm::Value::dump]. *) val dump_value : llvalue -> unit +(** [string_of_llvalue v] returns a string describing the value [v]. *) +val string_of_llvalue : llvalue -> string + (** [replace_all_uses_with old new] replaces all uses of the value [old] - * with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) + 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]. @@ -635,6 +724,7 @@ val set_operand : llvalue -> int -> llvalue -> unit 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] @@ -665,7 +755,11 @@ val is_null : llvalue -> bool otherwise. Similar to [llvm::isa]. *) val is_undef : llvalue -> bool +(** [constexpr_opcode v] returns an [Opcode.t] corresponding to constexpr + value [v], or [Opcode.Invalid] if [v] is not a constexpr. *) val constexpr_opcode : llvalue -> Opcode.t + + (** {7 Operations on instructions} *) (** [has_metadata i] returns whether or not the instruction [i] has any @@ -699,14 +793,22 @@ val mdstring : llcontext -> string -> llvalue val mdnode : llcontext -> llvalue array -> llvalue (** [get_mdstring v] returns the MDString. - * See the method [llvm::MDString::getString] *) + See the method [llvm::MDString::getString] *) val get_mdstring : llvalue -> string option -(** [get_named_metadata m name] return all the MDNodes belonging to the named - * metadata (if any). - * See the method [llvm::NamedMDNode::getOperand]. *) +(** [get_named_metadata m name] returns all the MDNodes belonging to the named + metadata (if any). + See the method [llvm::NamedMDNode::getOperand]. *) val get_named_metadata : llmodule -> string -> llvalue array +(** [add_named_metadata_operand m name v] adds [v] as the last operand of + metadata named [name] in module [m]. If the metadata does not exist, + it is created. + See the methods [llvm::Module::getNamedMetadata()] and + [llvm::MDNode::addOperand()]. *) +val add_named_metadata_operand : llmodule -> string -> llvalue -> unit + + (** {7 Operations on scalar constants} *) (** [const_int ty i] returns the integer constant of type [ty] and value [i]. @@ -718,15 +820,14 @@ val const_int : lltype -> int -> llvalue val const_of_int64 : lltype -> Int64.t -> bool -> llvalue (** [int64_of_const c] returns the int64 value of the [c] constant integer. - * None is returned if this is not an integer constant, or bitwidth exceeds 64. - * See the method [llvm::ConstantInt::getSExtValue].*) + None is returned if this is not an integer constant, or bitwidth exceeds 64. + See the method [llvm::ConstantInt::getSExtValue].*) val int64_of_const : llvalue -> Int64.t option (** [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]. *) + 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 @@ -736,7 +837,6 @@ val const_float : lltype -> float -> llvalue 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 @@ -777,7 +877,6 @@ val const_named_struct : lltype -> llvalue array -> llvalue [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]. *) @@ -929,13 +1028,11 @@ val const_xor : llvalue -> llvalue -> llvalue 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]. *) @@ -961,7 +1058,6 @@ val const_gep : llvalue -> llvalue array -> llvalue 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]. *) @@ -1027,50 +1123,44 @@ val const_bitcast : llvalue -> lltype -> llvalue 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_intcast c ty ~is_signed] returns a constant sext/zext, bitcast, + or trunc for integer -> integer casts of constant [c] to type [ty]. + When converting a narrower value to a wider one, whether sext or zext + will be used is controlled by [is_signed]. + See the method [llvm::ConstantExpr::getIntegerCast]. *) +val const_intcast : llvalue -> lltype -> is_signed:bool -> 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 @@ -1079,31 +1169,25 @@ val const_extractelement : llvalue -> llvalue -> llvalue 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 - +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]. *) @@ -1145,7 +1229,6 @@ val visibility : llvalue -> Visibility.t [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 @@ -1163,15 +1246,12 @@ val set_alignment : int -> llvalue -> unit 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 - +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 @@ -1179,21 +1259,17 @@ val declare_qualified_global : lltype -> string -> int -> llmodule -> 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 - +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 @@ -1204,13 +1280,11 @@ val delete_global : llvalue -> unit 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 @@ -1225,13 +1299,11 @@ val fold_left_globals : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a 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 @@ -1250,7 +1322,6 @@ val is_global_constant : llvalue -> bool 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 @@ -1275,6 +1346,26 @@ val is_thread_local : llvalue -> bool See the method [llvm::GlobalVariable::setThreadLocal]. *) val set_thread_local : bool -> llvalue -> unit +(** [is_thread_local gv] returns the thread local mode of the global + variable [gv]. + See the method [llvm::GlobalVariable::getThreadLocalMode]. *) +val thread_local_mode : llvalue -> ThreadLocalMode.t + +(** [set_thread_local c gv] sets the thread local mode of the global + variable [gv]. + See the method [llvm::GlobalVariable::setThreadLocalMode]. *) +val set_thread_local_mode : ThreadLocalMode.t -> llvalue -> unit + +(** [is_externally_initialized gv] returns [true] if the global + variable [gv] is externally initialized and [false] otherwise. + See the method [llvm::GlobalVariable::isExternallyInitialized]. *) +val is_externally_initialized : llvalue -> bool + +(** [set_externally_initialized c gv] sets the global variable [gv] to be + externally initialized if [c] is [true] and not otherwise. + See the method [llvm::GlobalVariable::setExternallyInitialized]. *) +val set_externally_initialized : bool -> llvalue -> unit + (** {7 Operations on aliases} *) @@ -1284,7 +1375,6 @@ val set_thread_local : bool -> llvalue -> unit 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 @@ -1293,20 +1383,17 @@ val add_alias : llmodule -> lltype -> llvalue -> string -> llvalue 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 @@ -1317,13 +1404,11 @@ val delete_function : llvalue -> unit 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 @@ -1338,12 +1423,10 @@ val fold_left_functions : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a 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 @@ -1365,7 +1448,6 @@ val function_call_conv : llvalue -> int 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]. *) @@ -1379,14 +1461,19 @@ val set_gc : string option -> llvalue -> unit [f]. *) val add_function_attr : llvalue -> Attribute.t -> unit +(** [add_target_dependent_function_attr f a] adds target-dependent attribute + [a] to function [f]. *) +val add_target_dependent_function_attr : llvalue -> string -> string -> unit + (** [function_attr f] returns the function attribute for the function [f]. - * See the method [llvm::Function::getAttributes] *) + See the method [llvm::Function::getAttributes] *) val function_attr : llvalue -> Attribute.t list (** [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]. @@ -1398,8 +1485,8 @@ val params : llvalue -> llvalue array val param : llvalue -> int -> llvalue (** [param_attr p] returns the attributes of parameter [p]. - * See the methods [llvm::Function::getAttributes] and - * [llvm::Attributes::getParamAttributes] *) + See the methods [llvm::Function::getAttributes] and + [llvm::Attributes::getParamAttributes] *) val param_attr : llvalue -> Attribute.t list (** [param_parent p] returns the parent function that owns the parameter. @@ -1435,7 +1522,6 @@ val param_end : llvalue -> (llvalue, llvalue) llrev_pos 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 @@ -1468,18 +1554,28 @@ val entry_block : llvalue -> llbasicblock See the method [llvm::BasicBlock::eraseFromParent]. *) val delete_block : llbasicblock -> unit +(** [remove_block bb] removes the basic block [bb] from its parent function. + See the method [llvm::BasicBlock::removeFromParent]. *) +val remove_block : llbasicblock -> unit + +(** [move_block_before pos bb] moves the basic block [bb] before [pos]. + See the method [llvm::BasicBlock::moveBefore]. *) +val move_block_before : llbasicblock -> llbasicblock -> unit + +(** [move_block_after pos bb] moves the basic block [bb] after [pos]. + See the method [llvm::BasicBlock::moveAfter]. *) +val move_block_after : llbasicblock -> 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 @@ -1490,13 +1586,11 @@ val block_parent : llbasicblock -> llvalue 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 @@ -1511,11 +1605,11 @@ val fold_left_blocks : ('a -> llbasicblock -> 'a) -> 'a -> llvalue -> 'a 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]. +(** [block_pred bb] returns the basic block list position preceding [After bb]. See the method [llvm::Function::iterator::operator--]. *) val block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos +(** [block_terminator bb] returns the terminator of the basic block [bb]. *) val block_terminator : llbasicblock -> llvalue option (** [rev_iter_blocks f fn] applies function [f] to each of the basic blocks @@ -1544,18 +1638,20 @@ val block_of_value : llvalue -> llbasicblock See the method [llvm::Instruction::getParent]. *) val instr_parent : llvalue -> llbasicblock +(** [delete_instruction i] deletes the instruction [i]. + * See the method [llvm::Instruction::eraseFromParent]. *) +val delete_instruction : llvalue -> unit + (** [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 @@ -1570,20 +1666,23 @@ val fold_left_instrs: ('a -> llvalue -> 'a) -> 'a -> llbasicblock -> 'a 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 +(** [inst_opcode i] returns the [Opcode.t] corresponding to instruction [i], + or [Opcode.Invalid] if [i] is not an instruction. *) val instr_opcode : llvalue -> Opcode.t +(** [icmp_predicate i] returns the [Icmp.t] corresponding to an [icmp] + instruction [i]. *) val icmp_predicate : llvalue -> Icmp.t option + (** {7 Operations on call sites} *) (** [instruction_call_conv ci] is the calling convention for the call or invoke @@ -1592,7 +1691,6 @@ val icmp_predicate : llvalue -> Icmp.t option [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}. @@ -1600,7 +1698,6 @@ val instruction_call_conv: llvalue -> int 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. *) @@ -1611,7 +1708,8 @@ val add_instruction_param_attr : llvalue -> int -> Attribute.t -> unit return value. *) val remove_instruction_param_attr : llvalue -> int -> Attribute.t -> unit -(** {Operations on call instructions (only)} *) + +(** {7 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. @@ -1623,20 +1721,33 @@ val is_tail_call : llvalue -> bool See the method [llvm::CallInst::setTailCall]. *) val set_tail_call : bool -> llvalue -> unit + +(** {7 Operations on load/store instructions (only)} *) + +(** [is_volatile i] is [true] if the load or store instruction [i] is marked + as volatile. + See the methods [llvm::LoadInst::isVolatile] and + [llvm::StoreInst::isVolatile]. *) +val is_volatile : llvalue -> bool + +(** [set_volatile v i] marks the load or store instruction [i] as volatile + if [v] is [true], unmarks otherwise. + See the methods [llvm::LoadInst::setVolatile] and + [llvm::StoreInst::setVolatile]. *) +val set_volatile : 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 -(** [delete_instruction i] deletes the instruction [i]. - * See the method [llvm::Instruction::eraseFromParent]. *) -val delete_instruction : llvalue -> unit + (** {6 Instruction builders} *) @@ -1663,7 +1774,6 @@ val builder_at_end : llcontext -> llbasicblock -> llbuilder 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 @@ -1691,18 +1801,15 @@ val insert_into_builder : llvalue -> string -> llbuilder -> unit 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]. *) @@ -1729,7 +1836,6 @@ val build_ret : llvalue -> llbuilder -> llvalue 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]. @@ -1771,8 +1877,8 @@ val build_free : llvalue -> llbuilder -> llvalue val add_case : llvalue -> llvalue -> llbasicblock -> unit (** [switch_default_dest sw] returns the default destination of the [switch] - * instruction. - * See the method [llvm:;SwitchInst::getDefaultDest]. **) + instruction. + See the method [llvm:;SwitchInst::getDefaultDest]. **) val switch_default_dest : llvalue -> llbasicblock (** [build_indirect_br addr count b] creates a @@ -1782,13 +1888,11 @@ val switch_default_dest : llvalue -> llbasicblock 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]. @@ -1811,9 +1915,9 @@ val set_cleanup : llvalue -> bool -> unit See the method [llvm::LandingPadInst::addClause]. *) val add_clause : llvalue -> llvalue -> unit -(* [build_resume exn b] builds a [resume exn] instruction - * at the position specified by the instruction builder [b]. - * See the method [llvm::LLVMBuilder::CreateResume] *) +(** [build_resume exn b] builds a [resume exn] instruction + at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateResume] *) val build_resume : llvalue -> llbuilder -> llvalue (** [build_unreachable b] creates an @@ -1831,175 +1935,150 @@ val build_unreachable : llbuilder -> llvalue 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]. @@ -2007,7 +2086,6 @@ val build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue 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]. @@ -2015,7 +2093,6 @@ val build_neg : llvalue -> string -> llbuilder -> llvalue 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]. @@ -2023,7 +2100,6 @@ val build_nsw_neg : llvalue -> string -> llbuilder -> llvalue 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]. @@ -2031,7 +2107,6 @@ val build_nuw_neg : llvalue -> string -> llbuilder -> llvalue 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]. @@ -2040,7 +2115,6 @@ val build_fneg : llvalue -> string -> llbuilder -> llvalue val build_not : llvalue -> string -> llbuilder -> llvalue - (** {7 Memory} *) (** [build_alloca ty name b] creates a @@ -2049,7 +2123,6 @@ val build_not : llvalue -> string -> llbuilder -> llvalue 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]. @@ -2063,13 +2136,19 @@ val build_array_alloca : lltype -> llvalue -> string -> llbuilder -> 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_atomicrmw op ptr val o st b] creates an [atomicrmw] instruction with + operation [op] performed on pointer [ptr] and value [val] with ordering [o] + and singlethread flag set to [st] at the position specified by + the instruction builder [b]. + See the method [llvm::IRBuilder::CreateAtomicRMW]. *) +val build_atomicrmw : AtomicRMWBinOp.t -> llvalue -> llvalue -> + AtomicOrdering.t -> bool -> string -> llbuilder -> llvalue (** [build_gep p indices name b] creates a [%name = getelementptr %p, indices...] @@ -2077,7 +2156,6 @@ val build_store : llvalue -> llvalue -> llbuilder -> llvalue 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]. @@ -2097,7 +2175,6 @@ val build_struct_gep : llvalue -> int -> string -> llbuilder -> 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]. @@ -2105,7 +2182,6 @@ val build_global_string : string -> string -> llbuilder -> llvalue val build_global_stringptr : string -> string -> llbuilder -> llvalue - (** {7 Casts} *) (** [build_trunc v ty name b] creates a @@ -2114,84 +2190,72 @@ val build_global_stringptr : string -> string -> llbuilder -> llvalue 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]. *) @@ -2215,20 +2279,17 @@ val build_trunc_or_bitcast : llvalue -> lltype -> string -> llbuilder -> 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 @@ -2262,7 +2323,6 @@ val build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> 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]. @@ -2276,7 +2336,6 @@ val build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> 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]. @@ -2318,14 +2377,12 @@ val build_insertvalue : llvalue -> llvalue -> int -> string -> llbuilder -> 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]. @@ -2333,7 +2390,6 @@ val build_is_not_null : llvalue -> string -> llbuilder -> llvalue val build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue - (** {6 Memory buffers} *) module MemoryBuffer : sig @@ -2342,9 +2398,16 @@ module MemoryBuffer : sig raised. *) val of_file : string -> llmemorybuffer - (** [stdin ()] is the memory buffer containing the contents of standard input. + (** [of_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 + + (** [of_string ~name s] is the memory buffer containing the contents of string [s]. + The name of memory buffer is set to [name] if it is provided. *) + val of_string : ?name:string -> string -> llmemorybuffer + + (** [as_string mb] is the string containing the contents of memory buffer [mb]. *) + val as_string : llmemorybuffer -> string (** Disposes of a memory buffer. *) val dispose : llmemorybuffer -> unit @@ -2371,14 +2434,12 @@ module PassManager : sig 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. @@ -2390,7 +2451,6 @@ module PassManager : sig 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 diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index c984bd154cc27..d5ebdcd3e31af 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -1,4 +1,4 @@ -/*===-- llvm_ocaml.c - LLVM Ocaml Glue --------------------------*- C++ -*-===*\ +/*===-- llvm_ocaml.c - LLVM OCaml Glue --------------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| @@ -33,6 +33,7 @@ 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; } @@ -50,6 +51,30 @@ static void llvm_raise(value Prototype, char *Message) { #endif } +static value llvm_fatal_error_handler; + +static void llvm_fatal_error_trampoline(const char *Reason) { + callback(llvm_fatal_error_handler, copy_string(Reason)); +} + +CAMLprim value llvm_install_fatal_error_handler(value Handler) { + LLVMInstallFatalErrorHandler(llvm_fatal_error_trampoline); + llvm_fatal_error_handler = Handler; + caml_register_global_root(&llvm_fatal_error_handler); + return Val_unit; +} + +CAMLprim value llvm_reset_fatal_error_handler(value Unit) { + caml_remove_global_root(&llvm_fatal_error_handler); + LLVMResetFatalErrorHandler(); + return Val_unit; +} + +CAMLprim value llvm_enable_pretty_stacktrace(value Unit) { + LLVMEnablePrettyStackTrace(); + return Val_unit; +} + static value alloc_variant(int tag, void *Value) { value Iter = alloc_small(1, tag); Field(Iter, 0) = Val_op(Value); @@ -158,6 +183,27 @@ CAMLprim value llvm_dump_module(LLVMModuleRef M) { return Val_unit; } +/* string -> llmodule -> unit */ +CAMLprim value llvm_print_module(value Filename, LLVMModuleRef M) { + char* Message; + if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) { + llvm_raise(llvm_ioerror_exn, Message); + } + + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_string_of_llmodule(LLVMModuleRef M) { + char* ModuleCStr; + ModuleCStr = LLVMPrintModuleToString(M); + + value ModuleStr = caml_copy_string(ModuleCStr); + LLVMDisposeMessage(ModuleCStr); + + return ModuleStr; +} + /* llmodule -> string -> unit */ CAMLprim value llvm_set_module_inline_asm(LLVMModuleRef M, value Asm) { LLVMSetModuleInlineAsm(M, String_val(Asm)); @@ -180,6 +226,23 @@ CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) { return LLVMGetTypeContext(Ty); } +/* lltype -> unit */ +CAMLprim value llvm_dump_type(LLVMTypeRef Val) { + LLVMDumpType(Val); + return Val_unit; +} + +/* lltype -> string */ +CAMLprim value llvm_string_of_lltype(LLVMTypeRef M) { + char* TypeCStr; + TypeCStr = LLVMPrintTypeToString(M); + + value TypeStr = caml_copy_string(TypeCStr); + LLVMDisposeMessage(TypeCStr); + + return TypeStr; +} + /*--... Operations on integer types ........................................--*/ /* llcontext -> lltype */ @@ -244,11 +307,6 @@ 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 */ @@ -386,6 +444,11 @@ CAMLprim LLVMTypeRef llvm_label_type(LLVMContextRef Context) { return LLVMLabelTypeInContext(Context); } +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_x86_mmx_type(LLVMContextRef Context) { + return LLVMX86MMXTypeInContext(Context); +} + CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name) { CAMLparam1(Name); @@ -416,6 +479,8 @@ enum ValueKind { BlockAddress, ConstantAggregateZero, ConstantArray, + ConstantDataArray, + ConstantDataVector, ConstantExpr, ConstantFP, ConstantInt, @@ -441,6 +506,8 @@ CAMLprim value llvm_classify_value(LLVMValueRef Val) { DEFINE_CASE(Val, BlockAddress); DEFINE_CASE(Val, ConstantAggregateZero); DEFINE_CASE(Val, ConstantArray); + DEFINE_CASE(Val, ConstantDataArray); + DEFINE_CASE(Val, ConstantDataVector); DEFINE_CASE(Val, ConstantExpr); DEFINE_CASE(Val, ConstantFP); DEFINE_CASE(Val, ConstantInt); @@ -485,6 +552,24 @@ CAMLprim value llvm_dump_value(LLVMValueRef Val) { return Val_unit; } +/* llvalue -> string */ +CAMLprim value llvm_string_of_llvalue(LLVMValueRef M) { + char* ValueCStr; + ValueCStr = LLVMPrintValueToString(M); + + value ValueStr = caml_copy_string(ValueCStr); + LLVMDisposeMessage(ValueCStr); + + return ValueStr; +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_replace_all_uses_with(LLVMValueRef OldVal, + LLVMValueRef NewVal) { + LLVMReplaceAllUsesWith(OldVal, NewVal); + return Val_unit; +} + /*--... Operations on users ................................................--*/ /* llvalue -> int -> llvalue */ @@ -590,14 +675,22 @@ CAMLprim value llvm_get_mdstring(LLVMValueRef V) { CAMLreturn(Val_int(0)); } -CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value name) +/* llmodule -> string -> llvalue array */ +CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value Name) { - CAMLparam1(name); + CAMLparam1(Name); CAMLlocal1(Nodes); - Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(name)), 0); - LLVMGetNamedMetadataOperands(M, String_val(name), (LLVMValueRef *) Nodes); + Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(Name)), 0); + LLVMGetNamedMetadataOperands(M, String_val(Name), (LLVMValueRef *) Nodes); CAMLreturn(Nodes); } + +/* llmodule -> string -> llvalue -> unit */ +CAMLprim value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val) { + LLVMAddNamedMetadataOperand(M, String_val(Name), Val); + return Val_unit; +} + /*--... Operations on scalar constants .....................................--*/ /* lltype -> int -> llvalue */ @@ -718,6 +811,12 @@ CAMLprim LLVMValueRef llvm_const_in_bounds_gep(LLVMValueRef ConstantVal, Wosize_val(Indices)); } +/* llvalue -> lltype -> is_signed:bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_intcast(LLVMValueRef CV, LLVMTypeRef T, + value IsSigned) { + return LLVMConstIntCast(CV, T, Bool_val(IsSigned)); +} + /* llvalue -> int array -> llvalue */ CAMLprim LLVMValueRef llvm_const_extractvalue(LLVMValueRef Aggregate, value Indices) { @@ -877,7 +976,8 @@ CAMLprim LLVMValueRef llvm_declare_qualified_global(LLVMTypeRef Ty, value Name, LLVMPointerType(Ty, Int_val(AddressSpace))); return GlobalVar; } - return LLVMAddGlobal(M, Ty, String_val(Name)); + return LLVMAddGlobalInAddressSpace(M, Ty, String_val(Name), + Int_val(AddressSpace)); } /* string -> llmodule -> llvalue option */ @@ -945,6 +1045,30 @@ CAMLprim value llvm_set_thread_local(value IsThreadLocal, return Val_unit; } +/* llvalue -> ThreadLocalMode.t */ +CAMLprim value llvm_thread_local_mode(LLVMValueRef GlobalVar) { + return Val_int(LLVMGetThreadLocalMode(GlobalVar)); +} + +/* ThreadLocalMode.t -> llvalue -> unit */ +CAMLprim value llvm_set_thread_local_mode(value ThreadLocalMode, + LLVMValueRef GlobalVar) { + LLVMSetThreadLocalMode(GlobalVar, Int_val(ThreadLocalMode)); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_externally_initialized(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsExternallyInitialized(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_externally_initialized(value IsExternallyInitialized, + LLVMValueRef GlobalVar) { + LLVMSetExternallyInitialized(GlobalVar, Bool_val(IsExternallyInitialized)); + return Val_unit; +} + /* llvalue -> bool */ CAMLprim value llvm_is_global_constant(LLVMValueRef GlobalVar) { return Val_bool(LLVMIsGlobalConstant(GlobalVar)); @@ -1051,6 +1175,13 @@ CAMLprim value llvm_add_function_attr(LLVMValueRef Arg, value PA) { return Val_unit; } +/* llvalue -> string -> string -> unit */ +CAMLprim value llvm_add_target_dependent_function_attr( + LLVMValueRef Arg, value A, value V) { + LLVMAddTargetDependentFunctionAttr(Arg, String_val(A), String_val(V)); + return Val_unit; +} + /* llvalue -> int32 */ CAMLprim value llvm_function_attr(LLVMValueRef Fn) { @@ -1135,6 +1266,24 @@ CAMLprim value llvm_delete_block(LLVMBasicBlockRef BB) { return Val_unit; } +/* llbasicblock -> unit */ +CAMLprim value llvm_remove_block(LLVMBasicBlockRef BB) { + LLVMRemoveBasicBlockFromParent(BB); + return Val_unit; +} + +/* llbasicblock -> llbasicblock -> unit */ +CAMLprim value llvm_move_block_before(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) { + LLVMMoveBasicBlockBefore(BB, Pos); + return Val_unit; +} + +/* llbasicblock -> llbasicblock -> unit */ +CAMLprim value llvm_move_block_after(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) { + LLVMMoveBasicBlockAfter(BB, Pos); + return Val_unit; +} + /* string -> llvalue -> llbasicblock */ CAMLprim LLVMBasicBlockRef llvm_append_block(LLVMContextRef Context, value Name, LLVMValueRef Fn) { @@ -1167,7 +1316,7 @@ CAMLprim value llvm_instr_get_opcode(LLVMValueRef Inst) { return Val_int(o); } -/* llvalue -> ICmp.t */ +/* llvalue -> ICmp.t option */ CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) { CAMLparam0(); int x = LLVMGetICmpPredicate(Val); @@ -1223,6 +1372,20 @@ CAMLprim value llvm_set_tail_call(value IsTailCall, return Val_unit; } +/*--... Operations on load/store instructions (only)........................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_volatile(LLVMValueRef MemoryInst) { + return Val_bool(LLVMGetVolatile(MemoryInst)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_volatile(value IsVolatile, + LLVMValueRef MemoryInst) { + LLVMSetVolatile(MemoryInst, Bool_val(IsVolatile)); + return Val_unit; +} + /*--... Operations on phi nodes ............................................--*/ /* (llvalue * llbasicblock) -> llvalue -> unit */ @@ -1271,7 +1434,7 @@ static void llvm_finalize_builder(value B) { } static struct custom_operations builder_ops = { - (char *) "IRBuilder", + (char *) "LLVMIRBuilder", llvm_finalize_builder, custom_compare_default, custom_hash_default, @@ -1694,6 +1857,24 @@ CAMLprim LLVMValueRef llvm_build_store(LLVMValueRef Value, LLVMValueRef Pointer, return LLVMBuildStore(Builder_val(B), Value, Pointer); } +/* AtomicRMWBinOp.t -> llvalue -> llvalue -> AtomicOrdering.t -> + bool -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_atomicrmw_native(value BinOp, LLVMValueRef Ptr, + LLVMValueRef Val, value Ord, + value ST, value Name, value B) { + LLVMValueRef Instr; + Instr = LLVMBuildAtomicRMW(Builder_val(B), Int_val(BinOp), + Ptr, Val, Int_val(Ord), Bool_val(ST)); + LLVMSetValueName(Instr, String_val(Name)); + return Instr; +} + +CAMLprim LLVMValueRef llvm_build_atomicrmw_bytecode(value *argv, int argn) { + return llvm_build_atomicrmw_native(argv[0], (LLVMValueRef) argv[1], + (LLVMValueRef) argv[2], argv[3], + argv[4], argv[5], argv[6]); +} + /* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_gep(LLVMValueRef Pointer, value Indices, value Name, value B) { @@ -1960,7 +2141,6 @@ CAMLprim LLVMValueRef llvm_build_ptrdiff(LLVMValueRef LHS, LLVMValueRef RHS, return LLVMBuildPtrDiff(Builder_val(B), LHS, RHS, String_val(Name)); } - /*===-- Memory buffers ----------------------------------------------------===*/ /* string -> llmemorybuffer @@ -1989,6 +2169,30 @@ CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) { return MemBuf; } +/* ?name:string -> string -> llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) { + const char *NameCStr; + if(Name == Val_int(0)) + NameCStr = ""; + else + NameCStr = String_val(Field(Name, 0)); + + LLVMMemoryBufferRef MemBuf; + MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy( + String_val(String), caml_string_length(String), NameCStr); + + return MemBuf; +} + +/* llmemorybuffer -> string */ +CAMLprim value llvm_memorybuffer_as_string(LLVMMemoryBufferRef MemBuf) { + value String = caml_alloc_string(LLVMGetBufferSize(MemBuf)); + memcpy(String_val(String), LLVMGetBufferStart(MemBuf), + LLVMGetBufferSize(MemBuf)); + + return String; +} + /* llmemorybuffer -> unit */ CAMLprim value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) { LLVMDisposeMemoryBuffer(MemBuf); diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml index f4891e2b83bd9..974bd49c2813b 100644 --- a/bindings/ocaml/target/llvm_target.ml +++ b/bindings/ocaml/target/llvm_target.ml @@ -1,4 +1,4 @@ -(*===-- llvm_target.ml - LLVM Ocaml Interface ------------------*- OCaml -*-===* +(*===-- llvm_target.ml - LLVM OCaml Interface ------------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -13,30 +13,126 @@ module Endian = struct | Little end +module CodeGenOptLevel = struct + type t = + | None + | Less + | Default + | Aggressive +end + +module RelocMode = struct + type t = + | Default + | Static + | PIC + | DynamicNoPIC +end + +module CodeModel = struct + type t = + | Default + | JITDefault + | Small + | Kernel + | Medium + | Large +end + +module CodeGenFileType = struct + type t = + | AssemblyFile + | ObjectFile +end + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_target_exns" +let _ = register_exns (Error "") + module DataLayout = 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 dispose : t -> unit = "llvm_targetdata_dispose" -end - -external byte_order : DataLayout.t -> Endian.t = "llvm_byte_order" -external pointer_size : DataLayout.t -> int = "llvm_pointer_size" -external intptr_type : DataLayout.t -> Llvm.lltype = "LLVMIntPtrType" -external size_in_bits : DataLayout.t -> Llvm.lltype -> Int64.t - = "llvm_size_in_bits" -external store_size : DataLayout.t -> Llvm.lltype -> Int64.t = "llvm_store_size" -external abi_size : DataLayout.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" -external abi_align : DataLayout.t -> Llvm.lltype -> int = "llvm_abi_align" -external stack_align : DataLayout.t -> Llvm.lltype -> int = "llvm_stack_align" -external preferred_align : DataLayout.t -> Llvm.lltype -> int - = "llvm_preferred_align" -external preferred_align_of_global : DataLayout.t -> Llvm.llvalue -> int - = "llvm_preferred_align_of_global" -external element_at_offset : DataLayout.t -> Llvm.lltype -> Int64.t -> int - = "llvm_element_at_offset" -external offset_of_element : DataLayout.t -> Llvm.lltype -> int -> Int64.t - = "llvm_offset_of_element" + external of_string : string -> t = "llvm_datalayout_of_string" + external as_string : t -> string = "llvm_datalayout_as_string" + external add_to_pass_manager : [ t -> unit + = "llvm_datalayout_add_to_pass_manager" + external byte_order : t -> Endian.t = "llvm_datalayout_byte_order" + external pointer_size : t -> int = "llvm_datalayout_pointer_size" + external intptr_type : Llvm.llcontext -> t -> Llvm.lltype + = "llvm_datalayout_intptr_type" + external qualified_pointer_size : int -> t -> int + = "llvm_datalayout_qualified_pointer_size" + external qualified_intptr_type : Llvm.llcontext -> int -> t -> Llvm.lltype + = "llvm_datalayout_qualified_intptr_type" + external size_in_bits : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_size_in_bits" + external store_size : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_store_size" + external abi_size : Llvm.lltype -> t -> Int64.t + = "llvm_datalayout_abi_size" + external abi_align : Llvm.lltype -> t -> int + = "llvm_datalayout_abi_align" + external stack_align : Llvm.lltype -> t -> int + = "llvm_datalayout_stack_align" + external preferred_align : Llvm.lltype -> t -> int + = "llvm_datalayout_preferred_align" + external preferred_align_of_global : Llvm.llvalue -> t -> int + = "llvm_datalayout_preferred_align_of_global" + external element_at_offset : Llvm.lltype -> Int64.t -> t -> int + = "llvm_datalayout_element_at_offset" + external offset_of_element : Llvm.lltype -> int -> t -> Int64.t + = "llvm_datalayout_offset_of_element" +end + +module Target = struct + type t + + external default_triple : unit -> string = "llvm_target_default_triple" + external first : unit -> t option = "llvm_target_first" + external succ : t -> t option = "llvm_target_succ" + external by_name : string -> t option = "llvm_target_by_name" + external by_triple : string -> t = "llvm_target_by_triple" + external name : t -> string = "llvm_target_name" + external description : t -> string = "llvm_target_description" + external has_jit : t -> bool = "llvm_target_has_jit" + external has_target_machine : t -> bool = "llvm_target_has_target_machine" + external has_asm_backend : t -> bool = "llvm_target_has_asm_backend" + + let all () = + let rec step elem lst = + match elem with + | Some target -> step (succ target) (target :: lst) + | None -> lst + in + step (first ()) [] +end + +module TargetMachine = struct + type t + + external create : triple:string -> ?cpu:string -> ?features:string -> + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t -> + ?code_model:CodeModel.t -> Target.t -> t + = "llvm_create_targetmachine_bytecode" + "llvm_create_targetmachine_native" + external target : t -> Target.t + = "llvm_targetmachine_target" + external triple : t -> string + = "llvm_targetmachine_triple" + external cpu : t -> string + = "llvm_targetmachine_cpu" + external features : t -> string + = "llvm_targetmachine_features" + external data_layout : t -> DataLayout.t + = "llvm_targetmachine_data_layout" + external set_verbose_asm : bool -> t -> unit + = "llvm_targetmachine_set_verbose_asm" + external emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> + t -> unit + = "llvm_targetmachine_emit_to_file" + external emit_to_memory_buffer : Llvm.llmodule -> CodeGenFileType.t -> + t -> Llvm.llmemorybuffer + = "llvm_targetmachine_emit_to_memory_buffer" +end diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli index ab9c5e49eab86..4f5e7171634ff 100644 --- a/bindings/ocaml/target/llvm_target.mli +++ b/bindings/ocaml/target/llvm_target.mli @@ -1,4 +1,4 @@ -(*===-- llvm_target.mli - LLVM Ocaml Interface -----------------*- OCaml -*-===* +(*===-- llvm_target.mli - LLVM OCaml Interface -----------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Target Information. - This interface provides an ocaml API for LLVM target information, + This interface provides an OCaml API for LLVM target information, the classes in the Target library. *) module Endian : sig @@ -18,78 +18,205 @@ module Endian : sig | Little end +module CodeGenOptLevel : sig + type t = + | None + | Less + | Default + | Aggressive +end + +module RelocMode : sig + type t = + | Default + | Static + | PIC + | DynamicNoPIC +end + +module CodeModel : sig + type t = + | Default + | JITDefault + | Small + | Kernel + | Medium + | Large +end + +module CodeGenFileType : sig + type t = + | AssemblyFile + | ObjectFile +end + +(** {6 Exceptions} *) + +exception Error of string + +(** {6 Data Layout} *) + module DataLayout : sig type t - (** [DataLayout.create rep] parses the target data string representation [rep]. - See the constructor llvm::DataLayout::DataLayout. *) - external create : string -> t = "llvm_targetdata_create" + (** [of_string rep] parses the data layout string representation [rep]. + See the constructor [llvm::DataLayout::DataLayout]. *) + val of_string : string -> t + + (** [as_string dl] is the string representation of the data layout [dl]. + See the method [llvm::DataLayout::getStringRepresentation]. *) + val as_string : t -> string + + (** [add_to_pass_manager dl pm] adds the target data [dl] to + the pass manager [pm]. + See the method [llvm::PassManagerBase::add]. *) + val add_to_pass_manager : [ + t -> unit + + (** Returns the byte order of a target, either [Endian.Big] or + [Endian.Little]. + See the method [llvm::DataLayout::isLittleEndian]. *) + val byte_order : t -> Endian.t + + (** Returns the pointer size in bytes for a target. + See the method [llvm::DataLayout::getPointerSize]. *) + val pointer_size : t -> int + + (** Returns the integer type that is the same size as a pointer on a target. + See the method [llvm::DataLayout::getIntPtrType]. *) + val intptr_type : Llvm.llcontext -> t -> Llvm.lltype + + (** Returns the pointer size in bytes for a target in a given address space. + See the method [llvm::DataLayout::getPointerSize]. *) + val qualified_pointer_size : int -> t -> int + + (** Returns the integer type that is the same size as a pointer on a target + in a given address space. + See the method [llvm::DataLayout::getIntPtrType]. *) + val qualified_intptr_type : Llvm.llcontext -> int -> t -> Llvm.lltype + + (** Computes the size of a type in bits for a target. + See the method [llvm::DataLayout::getTypeSizeInBits]. *) + val size_in_bits : Llvm.lltype -> t -> Int64.t + + (** Computes the storage size of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeStoreSize]. *) + val store_size : Llvm.lltype -> t -> Int64.t + + (** Computes the ABI size of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeAllocSize]. *) + val abi_size : Llvm.lltype -> t -> Int64.t + + (** Computes the ABI alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val abi_align : Llvm.lltype -> t -> int + + (** Computes the call frame alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val stack_align : Llvm.lltype -> t -> int + + (** Computes the preferred alignment of a type in bytes for a target. + See the method [llvm::DataLayout::getTypeABISize]. *) + val preferred_align : Llvm.lltype -> t -> int + + (** Computes the preferred alignment of a global variable in bytes for + a target. See the method [llvm::DataLayout::getPreferredAlignment]. *) + val preferred_align_of_global : Llvm.llvalue -> t -> int + + (** Computes the structure element that contains the byte offset for a target. + See the method [llvm::StructLayout::getElementContainingOffset]. *) + val element_at_offset : Llvm.lltype -> Int64.t -> t -> int + + (** Computes the byte offset of the indexed struct element for a target. + See the method [llvm::StructLayout::getElementContainingOffset]. *) + val offset_of_element : Llvm.lltype -> int -> t -> Int64.t +end + +(** {6 Target} *) + +module Target : sig + type t + + (** [default_triple ()] returns the default target triple for current + platform. *) + val default_triple : unit -> string - (** [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" + (** [first ()] returns the first target in the registered targets + list, or [None]. *) + val first : unit -> t option - (** [as_string td] is the string representation of the target data [td]. - See the constructor llvm::DataLayout::DataLayout. *) - external as_string : t -> string = "llvm_targetdata_as_string" + (** [succ t] returns the next target after [t], or [None] + if [t] was the last target. *) + val succ : t -> t option - (** Deallocates a DataLayout. - See the destructor llvm::DataLayout::~DataLayout. *) - external dispose : t -> unit = "llvm_targetdata_dispose" + (** [all ()] returns a list of known targets. *) + val all : unit -> t list + + (** [by_name name] returns [Some t] if a target [t] named [name] is + registered, or [None] otherwise. *) + val by_name : string -> t option + + (** [by_triple triple] returns a target for a triple [triple], or raises + [Error] if [triple] does not correspond to a registered target. *) + val by_triple : string -> t + + (** Returns the name of a target. See [llvm::Target::getName]. *) + val name : t -> string + + (** Returns the description of a target. + See [llvm::Target::getDescription]. *) + val description : t -> string + + (** Returns [true] if the target has a JIT. *) + val has_jit : t -> bool + + (** Returns [true] if the target has a target machine associated. *) + val has_target_machine : t -> bool + + (** Returns [true] if the target has an ASM backend (required for + emitting output). *) + val has_asm_backend : t -> bool end -(** Returns the byte order of a target, either LLVMBigEndian or - LLVMLittleEndian. - See the method llvm::DataLayout::isLittleEndian. *) -external byte_order : DataLayout.t -> Endian.t = "llvm_byte_order" - -(** Returns the pointer size in bytes for a target. - See the method llvm::DataLayout::getPointerSize. *) -external pointer_size : DataLayout.t -> int = "llvm_pointer_size" - -(** Returns the integer type that is the same size as a pointer on a target. - See the method llvm::DataLayout::getIntPtrType. *) -external intptr_type : DataLayout.t -> Llvm.lltype = "LLVMIntPtrType" - -(** Computes the size of a type in bytes for a target. - See the method llvm::DataLayout::getTypeSizeInBits. *) -external size_in_bits : DataLayout.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::DataLayout::getTypeStoreSize. *) -external store_size : DataLayout.t -> Llvm.lltype -> Int64.t = "llvm_store_size" - -(** Computes the ABI size of a type in bytes for a target. - See the method llvm::DataLayout::getTypeAllocSize. *) -external abi_size : DataLayout.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" - -(** Computes the ABI alignment of a type in bytes for a target. - See the method llvm::DataLayout::getTypeABISize. *) -external abi_align : DataLayout.t -> Llvm.lltype -> int = "llvm_abi_align" - -(** Computes the call frame alignment of a type in bytes for a target. - See the method llvm::DataLayout::getTypeABISize. *) -external stack_align : DataLayout.t -> Llvm.lltype -> int = "llvm_stack_align" - -(** Computes the preferred alignment of a type in bytes for a target. - See the method llvm::DataLayout::getTypeABISize. *) -external preferred_align : DataLayout.t -> Llvm.lltype -> int - = "llvm_preferred_align" - -(** Computes the preferred alignment of a global variable in bytes for a target. - See the method llvm::DataLayout::getPreferredAlignment. *) -external preferred_align_of_global : DataLayout.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 : DataLayout.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 : DataLayout.t -> Llvm.lltype -> int -> Int64.t - = "llvm_offset_of_element" +(** {6 Target Machine} *) + +module TargetMachine : sig + type t + + (** Creates a new target machine. + See [llvm::Target::createTargetMachine]. *) + val create : triple:string -> ?cpu:string -> ?features:string -> + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t -> + ?code_model:CodeModel.t -> Target.t -> t + + (** Returns the Target used in a TargetMachine *) + val target : t -> Target.t + + (** Returns the triple used while creating this target machine. See + [llvm::TargetMachine::getTriple]. *) + val triple : t -> string + + (** Returns the CPU used while creating this target machine. See + [llvm::TargetMachine::getCPU]. *) + val cpu : t -> string + + (** Returns the feature string used while creating this target machine. See + [llvm::TargetMachine::getFeatureString]. *) + val features : t -> string + + (** Returns the data layout of this target machine. *) + val data_layout : t -> DataLayout.t + + (** Sets the assembly verbosity of this target machine. + See [llvm::TargetMachine::setAsmVerbosity]. *) + val set_verbose_asm : bool -> t -> unit + + (** Emits assembly or object data for the given module to the given + file or raise [Error]. *) + val emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> t -> unit + + (** Emits assembly or object data for the given module to a fresh memory + buffer or raise [Error]. *) + val emit_to_memory_buffer : Llvm.llmodule -> CodeGenFileType.t -> t -> + Llvm.llmemorybuffer +end diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c index 62fe789a52e23..9e8778aa61a6c 100644 --- a/bindings/ocaml/target/target_ocaml.c +++ b/bindings/ocaml/target/target_ocaml.c @@ -1,4 +1,4 @@ -/*===-- target_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +/*===-- target_ocaml.c - LLVM OCaml Glue ------------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| @@ -16,87 +16,375 @@ \*===----------------------------------------------------------------------===*/ #include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" #include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/custom.h" -/* string -> DataLayout.t */ -CAMLprim LLVMTargetDataRef llvm_targetdata_create(value StringRep) { - return LLVMCreateTargetData(String_val(StringRep)); -} +/*===---- Exceptions ------------------------------------------------------===*/ + +static value llvm_target_error_exn; -/* DataLayout.t -> [ unit */ -CAMLprim value llvm_targetdata_add(LLVMTargetDataRef TD, LLVMPassManagerRef PM){ - LLVMAddTargetData(TD, PM); +CAMLprim value llvm_register_target_exns(value Error) { + llvm_target_error_exn = Field(Error, 0); + register_global_root(&llvm_target_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 +} + +static value llvm_string_of_message(char* Message) { + value String = caml_copy_string(Message); + LLVMDisposeMessage(Message); + + return String; +} + +/*===---- Data Layout -----------------------------------------------------===*/ + +#define DataLayout_val(v) (*(LLVMTargetDataRef *)(Data_custom_val(v))) + +static void llvm_finalize_data_layout(value DataLayout) { + LLVMDisposeTargetData(DataLayout_val(DataLayout)); +} + +static struct custom_operations llvm_data_layout_ops = { + (char *) "LLVMDataLayout", + llvm_finalize_data_layout, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +value llvm_alloc_data_layout(LLVMTargetDataRef DataLayout) { + value V = alloc_custom(&llvm_data_layout_ops, sizeof(LLVMTargetDataRef), + 0, 1); + DataLayout_val(V) = DataLayout; + return V; +} + +/* string -> DataLayout.t */ +CAMLprim value llvm_datalayout_of_string(value StringRep) { + return llvm_alloc_data_layout(LLVMCreateTargetData(String_val(StringRep))); +} + /* DataLayout.t -> string */ -CAMLprim value llvm_targetdata_as_string(LLVMTargetDataRef TD) { - char *StringRep = LLVMCopyStringRepOfTargetData(TD); +CAMLprim value llvm_datalayout_as_string(value TD) { + char *StringRep = LLVMCopyStringRepOfTargetData(DataLayout_val(TD)); value Copy = copy_string(StringRep); LLVMDisposeMessage(StringRep); return Copy; } -/* DataLayout.t -> unit */ -CAMLprim value llvm_targetdata_dispose(LLVMTargetDataRef TD) { - LLVMDisposeTargetData(TD); +/* [ DataLayout.t -> unit */ +CAMLprim value llvm_datalayout_add_to_pass_manager(LLVMPassManagerRef PM, + value DL) { + LLVMAddTargetData(DataLayout_val(DL), PM); return Val_unit; } /* DataLayout.t -> Endian.t */ -CAMLprim value llvm_byte_order(LLVMTargetDataRef TD) { - return Val_int(LLVMByteOrder(TD)); +CAMLprim value llvm_datalayout_byte_order(value DL) { + return Val_int(LLVMByteOrder(DataLayout_val(DL))); } /* DataLayout.t -> int */ -CAMLprim value llvm_pointer_size(LLVMTargetDataRef TD) { - return Val_int(LLVMPointerSize(TD)); +CAMLprim value llvm_datalayout_pointer_size(value DL) { + return Val_int(LLVMPointerSize(DataLayout_val(DL))); +} + +/* Llvm.llcontext -> DataLayout.t -> Llvm.lltype */ +CAMLprim LLVMTypeRef llvm_datalayout_intptr_type(LLVMContextRef C, value DL) { + return LLVMIntPtrTypeInContext(C, DataLayout_val(DL));; +} + +/* int -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_qualified_pointer_size(value AS, value DL) { + return Val_int(LLVMPointerSizeForAS(DataLayout_val(DL), Int_val(AS))); +} + +/* Llvm.llcontext -> int -> DataLayout.t -> Llvm.lltype */ +CAMLprim LLVMTypeRef llvm_datalayout_qualified_intptr_type(LLVMContextRef C, + value AS, + value DL) { + return LLVMIntPtrTypeForASInContext(C, DataLayout_val(DL), Int_val(AS)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_size_in_bits(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMSizeOfTypeInBits(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_store_size(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMStoreSizeOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_abi_size(LLVMTypeRef Ty, value DL) { + return caml_copy_int64(LLVMABISizeOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_abi_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMABIAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_stack_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMCallFrameAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.lltype -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_preferred_align(LLVMTypeRef Ty, value DL) { + return Val_int(LLVMPreferredAlignmentOfType(DataLayout_val(DL), Ty)); +} + +/* Llvm.llvalue -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_preferred_align_of_global(LLVMValueRef GlobalVar, + value DL) { + return Val_int(LLVMPreferredAlignmentOfGlobal(DataLayout_val(DL), GlobalVar)); +} + +/* Llvm.lltype -> Int64.t -> DataLayout.t -> int */ +CAMLprim value llvm_datalayout_element_at_offset(LLVMTypeRef Ty, value Offset, + value DL) { + return Val_int(LLVMElementAtOffset(DataLayout_val(DL), Ty, + Int64_val(Offset))); +} + +/* Llvm.lltype -> int -> DataLayout.t -> Int64.t */ +CAMLprim value llvm_datalayout_offset_of_element(LLVMTypeRef Ty, value Index, + value DL) { + return caml_copy_int64(LLVMOffsetOfElement(DataLayout_val(DL), Ty, + Int_val(Index))); +} + +/*===---- Target ----------------------------------------------------------===*/ + +static value llvm_target_option(LLVMTargetRef Target) { + if(Target != NULL) { + value Result = caml_alloc_small(1, 0); + Store_field(Result, 0, (value) Target); + return Result; + } + + return Val_int(0); +} + +/* unit -> string */ +CAMLprim value llvm_target_default_triple(value Unit) { + char *TripleCStr = LLVMGetDefaultTargetTriple(); + value TripleStr = caml_copy_string(TripleCStr); + LLVMDisposeMessage(TripleCStr); + + return TripleStr; +} + +/* unit -> Target.t option */ +CAMLprim value llvm_target_first(value Unit) { + return llvm_target_option(LLVMGetFirstTarget()); +} + +/* Target.t -> Target.t option */ +CAMLprim value llvm_target_succ(LLVMTargetRef Target) { + return llvm_target_option(LLVMGetNextTarget(Target)); +} + +/* string -> Target.t option */ +CAMLprim value llvm_target_by_name(value Name) { + return llvm_target_option(LLVMGetTargetFromName(String_val(Name))); +} + +/* string -> Target.t */ +CAMLprim LLVMTargetRef llvm_target_by_triple(value Triple) { + LLVMTargetRef T; + char *Error; + + if(LLVMGetTargetFromTriple(String_val(Triple), &T, &Error)) + llvm_raise(llvm_target_error_exn, Error); + + return T; +} + +/* Target.t -> string */ +CAMLprim value llvm_target_name(LLVMTargetRef Target) { + return caml_copy_string(LLVMGetTargetName(Target)); +} + +/* Target.t -> string */ +CAMLprim value llvm_target_description(LLVMTargetRef Target) { + return caml_copy_string(LLVMGetTargetDescription(Target)); +} + +/* Target.t -> bool */ +CAMLprim value llvm_target_has_jit(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasJIT(Target)); +} + +/* Target.t -> bool */ +CAMLprim value llvm_target_has_target_machine(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasTargetMachine(Target)); } -/* DataLayout.t -> Llvm.lltype -> Int64.t */ -CAMLprim value llvm_size_in_bits(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return caml_copy_int64(LLVMSizeOfTypeInBits(TD, Ty)); +/* Target.t -> bool */ +CAMLprim value llvm_target_has_asm_backend(LLVMTargetRef Target) { + return Val_bool(LLVMTargetHasAsmBackend(Target)); } -/* DataLayout.t -> Llvm.lltype -> Int64.t */ -CAMLprim value llvm_store_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return caml_copy_int64(LLVMStoreSizeOfType(TD, Ty)); +/*===---- Target Machine --------------------------------------------------===*/ + +#define TargetMachine_val(v) (*(LLVMTargetMachineRef *)(Data_custom_val(v))) + +static void llvm_finalize_target_machine(value Machine) { + LLVMDisposeTargetMachine(TargetMachine_val(Machine)); +} + +static struct custom_operations llvm_target_machine_ops = { + (char *) "LLVMTargetMachine", + llvm_finalize_target_machine, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) { + value V = alloc_custom(&llvm_target_machine_ops, sizeof(LLVMTargetMachineRef), + 0, 1); + TargetMachine_val(V) = Machine; + return V; } -/* DataLayout.t -> Llvm.lltype -> Int64.t */ -CAMLprim value llvm_abi_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return caml_copy_int64(LLVMABISizeOfType(TD, Ty)); +/* triple:string -> ?cpu:string -> ?features:string + ?level:CodeGenOptLevel.t -> ?reloc_mode:RelocMode.t + ?code_model:CodeModel.t -> Target.t -> TargetMachine.t */ +CAMLprim value llvm_create_targetmachine_native(value Triple, value CPU, + value Features, value OptLevel, value RelocMode, + value CodeModel, LLVMTargetRef Target) { + LLVMTargetMachineRef Machine; + const char *CPUStr = "", *FeaturesStr = ""; + LLVMCodeGenOptLevel OptLevelEnum = LLVMCodeGenLevelDefault; + LLVMRelocMode RelocModeEnum = LLVMRelocDefault; + LLVMCodeModel CodeModelEnum = LLVMCodeModelDefault; + + if(CPU != Val_int(0)) + CPUStr = String_val(Field(CPU, 0)); + if(Features != Val_int(0)) + FeaturesStr = String_val(Field(Features, 0)); + if(OptLevel != Val_int(0)) + OptLevelEnum = Int_val(Field(OptLevel, 0)); + if(RelocMode != Val_int(0)) + RelocModeEnum = Int_val(Field(RelocMode, 0)); + if(CodeModel != Val_int(0)) + CodeModelEnum = Int_val(Field(CodeModel, 0)); + + Machine = LLVMCreateTargetMachine(Target, String_val(Triple), CPUStr, + FeaturesStr, OptLevelEnum, RelocModeEnum, CodeModelEnum); + + return llvm_alloc_targetmachine(Machine); } -/* DataLayout.t -> Llvm.lltype -> int */ -CAMLprim value llvm_abi_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return Val_int(LLVMABIAlignmentOfType(TD, Ty)); +CAMLprim value llvm_create_targetmachine_bytecode(value *argv, int argn) { + return llvm_create_targetmachine_native(argv[0], argv[1], argv[2], argv[3], + argv[4], argv[5], (LLVMTargetRef) argv[6]); } -/* DataLayout.t -> Llvm.lltype -> int */ -CAMLprim value llvm_stack_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return Val_int(LLVMCallFrameAlignmentOfType(TD, Ty)); +/* TargetMachine.t -> Target.t */ +CAMLprim LLVMTargetRef llvm_targetmachine_target(value Machine) { + return LLVMGetTargetMachineTarget(TargetMachine_val(Machine)); } -/* DataLayout.t -> Llvm.lltype -> int */ -CAMLprim value llvm_preferred_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return Val_int(LLVMPreferredAlignmentOfType(TD, Ty)); +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_triple(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineTriple( + TargetMachine_val(Machine))); } -/* DataLayout.t -> Llvm.llvalue -> int */ -CAMLprim value llvm_preferred_align_of_global(LLVMTargetDataRef TD, - LLVMValueRef GlobalVar) { - return Val_int(LLVMPreferredAlignmentOfGlobal(TD, GlobalVar)); +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_cpu(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineCPU( + TargetMachine_val(Machine))); } -/* DataLayout.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))); +/* TargetMachine.t -> string */ +CAMLprim value llvm_targetmachine_features(value Machine) { + return llvm_string_of_message(LLVMGetTargetMachineFeatureString( + TargetMachine_val(Machine))); } -/* DataLayout.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))); +/* TargetMachine.t -> DataLayout.t */ +CAMLprim value llvm_targetmachine_data_layout(value Machine) { + CAMLparam1(Machine); + CAMLlocal1(DataLayout); + + /* LLVMGetTargetMachineData returns a pointer owned by the TargetMachine, + so it is impossible to wrap it with llvm_alloc_target_data, which assumes + that OCaml owns the pointer. */ + LLVMTargetDataRef OrigDataLayout; + OrigDataLayout = LLVMGetTargetMachineData(TargetMachine_val(Machine)); + + char* TargetDataCStr; + TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); + DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); + LLVMDisposeMessage(TargetDataCStr); + + CAMLreturn(DataLayout); +} + +/* TargetMachine.t -> bool -> unit */ +CAMLprim value llvm_targetmachine_set_verbose_asm(value Machine, value Verb) { + LLVMSetTargetMachineAsmVerbosity(TargetMachine_val(Machine), Bool_val(Verb)); + return Val_unit; +} + +/* Llvm.llmodule -> CodeGenFileType.t -> string -> TargetMachine.t -> unit */ +CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, + value FileType, value FileName, value Machine) { + char* ErrorMessage; + + if(LLVMTargetMachineEmitToFile(TargetMachine_val(Machine), Module, + String_val(FileName), Int_val(FileType), + &ErrorMessage)) { + llvm_raise(llvm_target_error_exn, ErrorMessage); + } + + return Val_unit; +} + +/* Llvm.llmodule -> CodeGenFileType.t -> TargetMachine.t -> + Llvm.llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_targetmachine_emit_to_memory_buffer( + LLVMModuleRef Module, value FileType, + value Machine) { + char* ErrorMessage; + LLVMMemoryBufferRef Buffer; + + if(LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine), Module, + Int_val(FileType), &ErrorMessage, + &Buffer)) { + llvm_raise(llvm_target_error_exn, ErrorMessage); + } + + return Buffer; } diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile index 05fcd90097fe9..92c8396d9198a 100644 --- a/bindings/ocaml/transforms/Makefile +++ b/bindings/ocaml/transforms/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL := ../../.. -DIRS = scalar ipo +DIRS = scalar ipo vectorize passmgr_builder ocamldoc: $(Verb) for i in $(DIRS) ; do \ diff --git a/bindings/ocaml/transforms/ipo/Makefile b/bindings/ocaml/transforms/ipo/Makefile index 130d74c906070..ed67a7cb3a0d0 100644 --- a/bindings/ocaml/transforms/ipo/Makefile +++ b/bindings/ocaml/transforms/ipo/Makefile @@ -13,7 +13,6 @@ LEVEL := ../../../.. LIBRARYNAME := llvm_ipo -DONT_BUILD_RELINKED := 1 UsedComponents := ipo UsedOcamlInterfaces := llvm diff --git a/bindings/ocaml/transforms/ipo/ipo_ocaml.c b/bindings/ocaml/transforms/ipo/ipo_ocaml.c index 612015c099a7b..4ad8afbc9ccc4 100644 --- a/bindings/ocaml/transforms/ipo/ipo_ocaml.c +++ b/bindings/ocaml/transforms/ipo/ipo_ocaml.c @@ -1,4 +1,4 @@ -/*===-- ipo_ocaml.c - LLVM Ocaml Glue -------------------*- C++ -*-===*\ +/*===-- ipo_ocaml.c - LLVM OCaml Glue ---------------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| @@ -49,6 +49,12 @@ CAMLprim value llvm_add_function_inlining(LLVMPassManagerRef PM) { return Val_unit; } +/* [`Module] Llvm.PassManager.t -> unit */ +CAMLprim value llvm_add_always_inliner(LLVMPassManagerRef PM) { + LLVMAddAlwaysInlinerPass(PM); + return Val_unit; +} + /* [`Module] Llvm.PassManager.t -> unit */ CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) { LLVMAddAlwaysInlinerPass(PM); diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.ml b/bindings/ocaml/transforms/ipo/llvm_ipo.ml index 1562d10ae16e8..93f564a125715 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.ml +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.ml @@ -1,4 +1,4 @@ -(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===* +(*===-- llvm_ipo.ml - LLVM OCaml Interface --------------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -7,59 +7,31 @@ * *===----------------------------------------------------------------------===*) -(** IPO Transforms. - - This interface provides an ocaml API for LLVM interprocedural optimizations, the - classes in the [LLVMIPO] library. *) - -(** See llvm::createAddArgumentPromotionPass *) external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_argument_promotion" - -(** See llvm::createConstantMergePass function. *) external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_constant_merge" - -(** See llvm::createDeadArgEliminationPass function. *) external add_dead_arg_elimination : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" - -(** See llvm::createFunctionAttrsPass function. *) external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_function_attrs" - -(** See llvm::createFunctionInliningPass function. *) external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_function_inlining" - -(** See llvm::createGlobalDCEPass function. *) +external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_always_inliner" external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_global_dce" - -(** See llvm::createGlobalOptimizerPass function. *) external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_global_optimizer" - -(** See llvm::createIPConstantPropagationPass function. *) external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_ipc_propagation" - -(** See llvm::createPruneEHPass function. *) external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_prune_eh" - -(** See llvm::createIPSCCPPass function. *) external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_ipsccp" - -(** See llvm::createInternalizePass function. *) external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = "llvm_add_internalize" - -(** See llvm::createStripDeadPrototypesPass function. *) external add_strip_dead_prototypes : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" - -(** See llvm::createStripSymbolsPass function. *) external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.mli b/bindings/ocaml/transforms/ipo/llvm_ipo.mli index 636103d4f8cd4..1944c30b06c1b 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.mli +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.mli @@ -1,4 +1,4 @@ -(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===* +(*===-- llvm_ipo.mli - LLVM OCaml Interface -------------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -9,13 +9,13 @@ (** IPO Transforms. - This interface provides an ocaml API for LLVM interprocedural optimizations, the + This interface provides an OCaml API for LLVM interprocedural optimizations, the classes in the [LLVMIPO] library. *) (** See llvm::createAddArgumentPromotionPass *) external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_argument_promotion" + (** See llvm::createConstantMergePass function. *) external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_constant_merge" @@ -32,6 +32,10 @@ external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_function_inlining" +(** See llvm::createAlwaysInlinerPass function. *) +external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = + "llvm_add_always_inliner" + (** See llvm::createGlobalDCEPass function. *) external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_global_dce" diff --git a/bindings/ocaml/transforms/passmgr_builder/Makefile b/bindings/ocaml/transforms/passmgr_builder/Makefile new file mode 100644 index 0000000000000..54099dbb576df --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/passmgr_builder/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_passmgr_builder interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_passmgr_builder +UsedComponents := ipo +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml new file mode 100644 index 0000000000000..60df44611dc7a --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.ml @@ -0,0 +1,32 @@ +(*===-- llvm_passmgr_builder.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. + * + *===----------------------------------------------------------------------===*) + +type t + +external create : unit -> t + = "llvm_pmbuilder_create" +external set_opt_level : int -> t -> unit + = "llvm_pmbuilder_set_opt_level" +external set_size_level : int -> t -> unit + = "llvm_pmbuilder_set_size_level" +external set_disable_unit_at_a_time : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unit_at_a_time" +external set_disable_unroll_loops : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unroll_loops" +external use_inliner_with_threshold : int -> t -> unit + = "llvm_pmbuilder_use_inliner_with_threshold" +external populate_function_pass_manager + : [ `Function ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_function_pass_manager" +external populate_module_pass_manager + : [ `Module ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_module_pass_manager" +external populate_lto_pass_manager + : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit + = "llvm_pmbuilder_populate_lto_pass_manager" \ No newline at end of file diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli new file mode 100644 index 0000000000000..66b0981ea24dd --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli @@ -0,0 +1,54 @@ +(*===-- llvm_passmgr_builder.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. + * + *===----------------------------------------------------------------------===*) + +(** Pass Manager Builder. + + This interface provides an OCaml API for LLVM pass manager builder + from the [LLVMCore] library. *) + +type t + +(** See [llvm::PassManagerBuilder]. *) +external create : unit -> t + = "llvm_pmbuilder_create" + +(** See [llvm::PassManagerBuilder::OptLevel]. *) +external set_opt_level : int -> t -> unit + = "llvm_pmbuilder_set_opt_level" + +(** See [llvm::PassManagerBuilder::SizeLevel]. *) +external set_size_level : int -> t -> unit + = "llvm_pmbuilder_set_size_level" + +(** See [llvm::PassManagerBuilder::DisableUnitAtATime]. *) +external set_disable_unit_at_a_time : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unit_at_a_time" + +(** See [llvm::PassManagerBuilder::DisableUnrollLoops]. *) +external set_disable_unroll_loops : bool -> t -> unit + = "llvm_pmbuilder_set_disable_unroll_loops" + +(** See [llvm::PassManagerBuilder::Inliner]. *) +external use_inliner_with_threshold : int -> t -> unit + = "llvm_pmbuilder_use_inliner_with_threshold" + +(** See [llvm::PassManagerBuilder::populateFunctionPassManager]. *) +external populate_function_pass_manager + : [ `Function ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_function_pass_manager" + +(** See [llvm::PassManagerBuilder::populateModulePassManager]. *) +external populate_module_pass_manager + : [ `Module ] Llvm.PassManager.t -> t -> unit + = "llvm_pmbuilder_populate_module_pass_manager" + +(** See [llvm::PassManagerBuilder::populateLTOPassManager]. *) +external populate_lto_pass_manager + : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit + = "llvm_pmbuilder_populate_lto_pass_manager" \ No newline at end of file diff --git a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c new file mode 100644 index 0000000000000..a707856b822b9 --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c @@ -0,0 +1,113 @@ +/*===-- passmgr_builder_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/PassManagerBuilder.h" +#include "caml/mlvalues.h" +#include "caml/custom.h" +#include "caml/misc.h" + +#define PMBuilder_val(v) (*(LLVMPassManagerBuilderRef *)(Data_custom_val(v))) + +static void llvm_finalize_pmbuilder(value PMB) { + LLVMPassManagerBuilderDispose(PMBuilder_val(PMB)); +} + +static struct custom_operations pmbuilder_ops = { + (char *) "LLVMPassManagerBuilder", + llvm_finalize_pmbuilder, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +#ifdef custom_compare_ext_default + , custom_compare_ext_default +#endif +}; + +static value alloc_pmbuilder(LLVMPassManagerBuilderRef Ref) { + value Val = alloc_custom(&pmbuilder_ops, + sizeof(LLVMPassManagerBuilderRef), 0, 1); + PMBuilder_val(Val) = Ref; + return Val; +} + +/* t -> unit */ +CAMLprim value llvm_pmbuilder_create(value Unit) { + return alloc_pmbuilder(LLVMPassManagerBuilderCreate()); +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_opt_level(value OptLevel, value PMB) { + LLVMPassManagerBuilderSetOptLevel(PMBuilder_val(PMB), Int_val(OptLevel)); + return Val_unit; +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_size_level(value SizeLevel, value PMB) { + LLVMPassManagerBuilderSetSizeLevel(PMBuilder_val(PMB), Int_val(SizeLevel)); + return Val_unit; +} + +/* int -> t -> unit */ +CAMLprim value llvm_pmbuilder_use_inliner_with_threshold( + value Threshold, value PMB) { + LLVMPassManagerBuilderSetOptLevel(PMBuilder_val(PMB), Int_val(Threshold)); + return Val_unit; +} + +/* bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_disable_unit_at_a_time( + value DisableUnitAtATime, value PMB) { + LLVMPassManagerBuilderSetDisableUnitAtATime( + PMBuilder_val(PMB), Bool_val(DisableUnitAtATime)); + return Val_unit; +} + +/* bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_set_disable_unroll_loops( + value DisableUnroll, value PMB) { + LLVMPassManagerBuilderSetDisableUnrollLoops( + PMBuilder_val(PMB), Bool_val(DisableUnroll)); + return Val_unit; +} + +/* [ `Function ] Llvm.PassManager.t -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_function_pass_manager( + LLVMPassManagerRef PM, value PMB) { + LLVMPassManagerBuilderPopulateFunctionPassManager( + PMBuilder_val(PMB), PM); + return Val_unit; +} + +/* [ `Module ] Llvm.PassManager.t -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_module_pass_manager( + LLVMPassManagerRef PM, value PMB) { + LLVMPassManagerBuilderPopulateModulePassManager( + PMBuilder_val(PMB), PM); + return Val_unit; +} + +/* [ `Module ] Llvm.PassManager.t -> + internalize:bool -> run_inliner:bool -> t -> unit */ +CAMLprim value llvm_pmbuilder_populate_lto_pass_manager( + LLVMPassManagerRef PM, value Internalize, value RunInliner, + value PMB) { + LLVMPassManagerBuilderPopulateLTOPassManager( + PMBuilder_val(PMB), PM, + Bool_val(Internalize), Bool_val(RunInliner)); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/scalar/Makefile b/bindings/ocaml/transforms/scalar/Makefile index cbaffa4ea7ae2..6e250f66e852d 100644 --- a/bindings/ocaml/transforms/scalar/Makefile +++ b/bindings/ocaml/transforms/scalar/Makefile @@ -13,7 +13,6 @@ LEVEL := ../../../.. LIBRARYNAME := llvm_scalar_opts -DONT_BUILD_RELINKED := 1 UsedComponents := scalaropts UsedOcamlInterfaces := llvm diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml index 93ab1de25823c..958939dc3f359 100644 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml @@ -1,4 +1,4 @@ -(*===-- llvm_scalar_opts.ml - LLVM Ocaml Interface -------------*- OCaml -*-===* +(*===-- llvm_scalar_opts.ml - LLVM OCaml Interface -------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -109,3 +109,6 @@ external add_basic_alias_analysis : [ unit = "llvm_add_basic_alias_analysis" +external +add_partially_inline_lib_calls : [ unit + = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli index 121b3761282ae..d69abe209c45e 100644 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli @@ -1,4 +1,4 @@ -(*===-- llvm_scalar_opts.mli - LLVM Ocaml Interface ------------*- OCaml -*-===* +(*===-- llvm_scalar_opts.mli - LLVM OCaml Interface ------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -9,7 +9,7 @@ (** Scalar Transforms. - This interface provides an ocaml API for LLVM scalar transforms, the + This interface provides an OCaml API for LLVM scalar transforms, the classes in the [LLVMScalarOpts] library. *) (** See the [llvm::createConstantPropogationPass] function. *) @@ -162,3 +162,7 @@ external add_basic_alias_analysis : [ unit = "llvm_add_basic_alias_analysis" +(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) +external +add_partially_inline_lib_calls : [ unit + = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c index 7047ec04c741a..0a71bd7cad244 100644 --- a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c +++ b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c @@ -1,4 +1,4 @@ -/*===-- scalar_opts_ocaml.c - LLVM Ocaml Glue -------------------*- C++ -*-===*\ +/*===-- scalar_opts_ocaml.c - LLVM OCaml Glue -------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -7,7 +7,7 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* 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 *| @@ -199,3 +199,9 @@ CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { LLVMAddBasicAliasAnalysisPass(PM); return Val_unit; } + +/* [ unit */ +CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { + LLVMAddPartiallyInlineLibCallsPass(PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/vectorize/Makefile b/bindings/ocaml/transforms/vectorize/Makefile new file mode 100644 index 0000000000000..5a854d17805b1 --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/vectorize/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_vectorize_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_vectorize +UsedComponents := vectorize +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml new file mode 100644 index 0000000000000..4fc53c6da3edc --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml @@ -0,0 +1,15 @@ +(*===-- llvm_vectorize.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_bb_vectorize : [ unit + = "llvm_add_bb_vectorize" +external add_loop_vectorize : [ unit + = "llvm_add_loop_vectorize" +external add_slp_vectorize : [ unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli new file mode 100644 index 0000000000000..02530398512fd --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli @@ -0,0 +1,25 @@ +(*===-- llvm_vectorize.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. + * + *===----------------------------------------------------------------------===*) + +(** Vectorize Transforms. + + This interface provides an OCaml API for LLVM vectorize transforms, the + classes in the [LLVMVectorize] library. *) + +(** See the [llvm::createBBVectorizePass] function. *) +external add_bb_vectorize : [ unit + = "llvm_add_bb_vectorize" + +(** See the [llvm::createLoopVectorizePass] function. *) +external add_loop_vectorize : [ unit + = "llvm_add_loop_vectorize" + +(** See [llvm::createSLPVectorizerPass] function. *) +external add_slp_vectorize : [ unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c b/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c new file mode 100644 index 0000000000000..1c8104951c4aa --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/vectorize_ocaml.c @@ -0,0 +1,38 @@ +/*===-- vectorize_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/Vectorize.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [ unit */ +CAMLprim value llvm_add_bb_vectorize(LLVMPassManagerRef PM) { + LLVMAddBBVectorizePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_vectorize(LLVMPassManagerRef PM) { + LLVMAddLoopVectorizePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_slp_vectorize(LLVMPassManagerRef PM) { + LLVMAddSLPVectorizePass(PM); + return Val_unit; +} diff --git a/bindings/python/llvm/bit_reader.py b/bindings/python/llvm/bit_reader.py new file mode 100644 index 0000000000000..5bf5e22025a36 --- /dev/null +++ b/bindings/python/llvm/bit_reader.py @@ -0,0 +1,31 @@ + +from .common import LLVMObject +from .common import c_object_p +from .common import get_library +from . import enumerations +from .core import MemoryBuffer +from .core import Module +from .core import OpCode +from ctypes import POINTER +from ctypes import byref +from ctypes import c_char_p +from ctypes import cast +__all__ = ['parse_bitcode'] +lib = get_library() + +def parse_bitcode(mem_buffer): + """Input is .core.MemoryBuffer""" + module = c_object_p() + out = c_char_p(None) + result = lib.LLVMParseBitcode(mem_buffer, byref(module), byref(out)) + if result: + raise RuntimeError('LLVM Error: %s' % out.value) + m = Module(module) + m.take_ownership(mem_buffer) + return m + +def register_library(library): + library.LLVMParseBitcode.argtypes = [MemoryBuffer, POINTER(c_object_p), POINTER(c_char_p)] + library.LLVMParseBitcode.restype = bool + +register_library(lib) diff --git a/bindings/python/llvm/common.py b/bindings/python/llvm/common.py index 17c22b8ef4481..b177f7fa47e91 100644 --- a/bindings/python/llvm/common.py +++ b/bindings/python/llvm/common.py @@ -16,7 +16,7 @@ import platform # LLVM_VERSION: sync with PACKAGE_VERSION in autoconf/configure.ac and CMakeLists.txt # but leave out the 'svn' suffix. -LLVM_VERSION = '3.3' +LLVM_VERSION = '3.4' __all__ = [ 'c_object_p', diff --git a/bindings/python/llvm/core.py b/bindings/python/llvm/core.py index 67566374256e5..ebf57d44438bf 100644 --- a/bindings/python/llvm/core.py +++ b/bindings/python/llvm/core.py @@ -16,10 +16,19 @@ from . import enumerations from ctypes import POINTER from ctypes import byref from ctypes import c_char_p +from ctypes import c_uint __all__ = [ "lib", + "OpCode", "MemoryBuffer", + "Module", + "Value", + "Function", + "BasicBlock", + "Instruction", + "Context", + "PassRegistry" ] lib = get_library() @@ -83,16 +92,449 @@ class MemoryBuffer(LLVMObject): LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer) + def __len__(self): + return lib.LLVMGetBufferSize(self) + +class Value(LLVMObject): + + def __init__(self, value): + LLVMObject.__init__(self, value) + + @property + def name(self): + return lib.LLVMGetValueName(self) + + def dump(self): + lib.LLVMDumpValue(self) + + def get_operand(self, i): + return Value(lib.LLVMGetOperand(self, i)) + + def set_operand(self, i, v): + return lib.LLVMSetOperand(self, i, v) + + def __len__(self): + return lib.LLVMGetNumOperands(self) + +class Module(LLVMObject): + """Represents the top-level structure of an llvm program in an opaque object.""" + + def __init__(self, module, name=None, context=None): + LLVMObject.__init__(self, module, disposer=lib.LLVMDisposeModule) + + @classmethod + def CreateWithName(cls, module_id): + m = Module(lib.LLVMModuleCreateWithName(module_id)) + c = Context.GetGlobalContext().take_ownership(m) + return m + + @property + def datalayout(self): + return lib.LLVMGetDataLayout(self) + + @datalayout.setter + def datalayout(self, new_data_layout): + """new_data_layout is a string.""" + lib.LLVMSetDataLayout(self, new_data_layout) + + @property + def target(self): + return lib.LLVMGetTarget(self) + + @target.setter + def target(self, new_target): + """new_target is a string.""" + lib.LLVMSetTarget(self, new_target) + + def dump(self): + lib.LLVMDumpModule(self) + + class __function_iterator(object): + def __init__(self, module, reverse=False): + self.module = module + self.reverse = reverse + if self.reverse: + self.function = self.module.last + else: + self.function = self.module.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.function, Function): + raise StopIteration("") + result = self.function + if self.reverse: + self.function = self.function.prev + else: + self.function = self.function.next + return result + + def __iter__(self): + return Module.__function_iterator(self) + + def __reversed__(self): + return Module.__function_iterator(self, reverse=True) + + @property + def first(self): + return Function(lib.LLVMGetFirstFunction(self)) + + @property + def last(self): + return Function(lib.LLVMGetLastFunction(self)) + + def print_module_to_file(self, filename): + out = c_char_p(None) + # Result is inverted so 0 means everything was ok. + result = lib.LLVMPrintModuleToFile(self, filename, byref(out)) + if result: + raise RuntimeError("LLVM Error: %s" % out.value) + +class Function(Value): + + def __init__(self, value): + Value.__init__(self, value) + + @property + def next(self): + f = lib.LLVMGetNextFunction(self) + return f and Function(f) + + @property + def prev(self): + f = lib.LLVMGetPreviousFunction(self) + return f and Function(f) + + @property + def first(self): + b = lib.LLVMGetFirstBasicBlock(self) + return b and BasicBlock(b) + + @property + def last(self): + b = lib.LLVMGetLastBasicBlock(self) + return b and BasicBlock(b) + + class __bb_iterator(object): + def __init__(self, function, reverse=False): + self.function = function + self.reverse = reverse + if self.reverse: + self.bb = function.last + else: + self.bb = function.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.bb, BasicBlock): + raise StopIteration("") + result = self.bb + if self.reverse: + self.bb = self.bb.prev + else: + self.bb = self.bb.next + return result + + def __iter__(self): + return Function.__bb_iterator(self) + + def __reversed__(self): + return Function.__bb_iterator(self, reverse=True) + + def __len__(self): + return lib.LLVMCountBasicBlocks(self) + +class BasicBlock(LLVMObject): + + def __init__(self, value): + LLVMObject.__init__(self, value) + + @property + def next(self): + b = lib.LLVMGetNextBasicBlock(self) + return b and BasicBlock(b) + + @property + def prev(self): + b = lib.LLVMGetPreviousBasicBlock(self) + return b and BasicBlock(b) + + @property + def first(self): + i = lib.LLVMGetFirstInstruction(self) + return i and Instruction(i) + + @property + def last(self): + i = lib.LLVMGetLastInstruction(self) + return i and Instruction(i) + + def __as_value(self): + return Value(lib.LLVMBasicBlockAsValue(self)) + + @property + def name(self): + return lib.LLVMGetValueName(self.__as_value()) + + def dump(self): + lib.LLVMDumpValue(self.__as_value()) + + def get_operand(self, i): + return Value(lib.LLVMGetOperand(self.__as_value(), + i)) + + def set_operand(self, i, v): + return lib.LLVMSetOperand(self.__as_value(), + i, v) + + def __len__(self): + return lib.LLVMGetNumOperands(self.__as_value()) + + class __inst_iterator(object): + def __init__(self, bb, reverse=False): + self.bb = bb + self.reverse = reverse + if self.reverse: + self.inst = self.bb.last + else: + self.inst = self.bb.first + + def __iter__(self): + return self + + def next(self): + if not isinstance(self.inst, Instruction): + raise StopIteration("") + result = self.inst + if self.reverse: + self.inst = self.inst.prev + else: + self.inst = self.inst.next + return result + + def __iter__(self): + return BasicBlock.__inst_iterator(self) + + def __reversed__(self): + return BasicBlock.__inst_iterator(self, reverse=True) + + +class Instruction(Value): + + def __init__(self, value): + Value.__init__(self, value) + + @property + def next(self): + i = lib.LLVMGetNextInstruction(self) + return i and Instruction(i) + + @property + def prev(self): + i = lib.LLVMGetPreviousInstruction(self) + return i and Instruction(i) + + @property + def opcode(self): + return OpCode.from_value(lib.LLVMGetInstructionOpcode(self)) + +class Context(LLVMObject): + + def __init__(self, context=None): + if context is None: + context = lib.LLVMContextCreate() + LLVMObject.__init__(self, context, disposer=lib.LLVMContextDispose) + else: + LLVMObject.__init__(self, context) + + @classmethod + def GetGlobalContext(cls): + return Context(lib.LLVMGetGlobalContext()) + +class PassRegistry(LLVMObject): + """Represents an opaque pass registry object.""" + + def __init__(self): + LLVMObject.__init__(self, + lib.LLVMGetGlobalPassRegistry()) + def register_library(library): + # Initialization/Shutdown declarations. + library.LLVMInitializeCore.argtypes = [PassRegistry] + library.LLVMInitializeCore.restype = None + + library.LLVMInitializeTransformUtils.argtypes = [PassRegistry] + library.LLVMInitializeTransformUtils.restype = None + + library.LLVMInitializeScalarOpts.argtypes = [PassRegistry] + library.LLVMInitializeScalarOpts.restype = None + + library.LLVMInitializeObjCARCOpts.argtypes = [PassRegistry] + library.LLVMInitializeObjCARCOpts.restype = None + + library.LLVMInitializeVectorization.argtypes = [PassRegistry] + library.LLVMInitializeVectorization.restype = None + + library.LLVMInitializeInstCombine.argtypes = [PassRegistry] + library.LLVMInitializeInstCombine.restype = None + + library.LLVMInitializeIPO.argtypes = [PassRegistry] + library.LLVMInitializeIPO.restype = None + + library.LLVMInitializeInstrumentation.argtypes = [PassRegistry] + library.LLVMInitializeInstrumentation.restype = None + + library.LLVMInitializeAnalysis.argtypes = [PassRegistry] + library.LLVMInitializeAnalysis.restype = None + + library.LLVMInitializeIPA.argtypes = [PassRegistry] + library.LLVMInitializeIPA.restype = None + + library.LLVMInitializeCodeGen.argtypes = [PassRegistry] + library.LLVMInitializeCodeGen.restype = None + + library.LLVMInitializeTarget.argtypes = [PassRegistry] + library.LLVMInitializeTarget.restype = None + + library.LLVMShutdown.argtypes = [] + library.LLVMShutdown.restype = None + + # Pass Registry declarations. + library.LLVMGetGlobalPassRegistry.argtypes = [] + library.LLVMGetGlobalPassRegistry.restype = c_object_p + + # Context declarations. + library.LLVMContextCreate.argtypes = [] + library.LLVMContextCreate.restype = c_object_p + + library.LLVMContextDispose.argtypes = [Context] + library.LLVMContextDispose.restype = None + + library.LLVMGetGlobalContext.argtypes = [] + library.LLVMGetGlobalContext.restype = c_object_p + + # Memory buffer declarations library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p, POINTER(c_object_p), POINTER(c_char_p)] library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool + library.LLVMGetBufferSize.argtypes = [MemoryBuffer] + library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer] + # Module declarations + library.LLVMModuleCreateWithName.argtypes = [c_char_p] + library.LLVMModuleCreateWithName.restype = c_object_p + + library.LLVMDisposeModule.argtypes = [Module] + library.LLVMDisposeModule.restype = None + + library.LLVMGetDataLayout.argtypes = [Module] + library.LLVMGetDataLayout.restype = c_char_p + + library.LLVMSetDataLayout.argtypes = [Module, c_char_p] + library.LLVMSetDataLayout.restype = None + + library.LLVMGetTarget.argtypes = [Module] + library.LLVMGetTarget.restype = c_char_p + + library.LLVMSetTarget.argtypes = [Module, c_char_p] + library.LLVMSetTarget.restype = None + + library.LLVMDumpModule.argtypes = [Module] + library.LLVMDumpModule.restype = None + + library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p, + POINTER(c_char_p)] + library.LLVMPrintModuleToFile.restype = bool + + library.LLVMGetFirstFunction.argtypes = [Module] + library.LLVMGetFirstFunction.restype = c_object_p + + library.LLVMGetLastFunction.argtypes = [Module] + library.LLVMGetLastFunction.restype = c_object_p + + library.LLVMGetNextFunction.argtypes = [Function] + library.LLVMGetNextFunction.restype = c_object_p + + library.LLVMGetPreviousFunction.argtypes = [Function] + library.LLVMGetPreviousFunction.restype = c_object_p + + # Value declarations. + library.LLVMGetValueName.argtypes = [Value] + library.LLVMGetValueName.restype = c_char_p + + library.LLVMDumpValue.argtypes = [Value] + library.LLVMDumpValue.restype = None + + library.LLVMGetOperand.argtypes = [Value, c_uint] + library.LLVMGetOperand.restype = c_object_p + + library.LLVMSetOperand.argtypes = [Value, Value, c_uint] + library.LLVMSetOperand.restype = None + + library.LLVMGetNumOperands.argtypes = [Value] + library.LLVMGetNumOperands.restype = c_uint + + # Basic Block Declarations. + library.LLVMGetFirstBasicBlock.argtypes = [Function] + library.LLVMGetFirstBasicBlock.restype = c_object_p + + library.LLVMGetLastBasicBlock.argtypes = [Function] + library.LLVMGetLastBasicBlock.restype = c_object_p + + library.LLVMGetNextBasicBlock.argtypes = [BasicBlock] + library.LLVMGetNextBasicBlock.restype = c_object_p + + library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock] + library.LLVMGetPreviousBasicBlock.restype = c_object_p + + library.LLVMGetFirstInstruction.argtypes = [BasicBlock] + library.LLVMGetFirstInstruction.restype = c_object_p + + library.LLVMGetLastInstruction.argtypes = [BasicBlock] + library.LLVMGetLastInstruction.restype = c_object_p + + library.LLVMBasicBlockAsValue.argtypes = [BasicBlock] + library.LLVMBasicBlockAsValue.restype = c_object_p + + library.LLVMCountBasicBlocks.argtypes = [Function] + library.LLVMCountBasicBlocks.restype = c_uint + + # Instruction Declarations. + library.LLVMGetNextInstruction.argtypes = [Instruction] + library.LLVMGetNextInstruction.restype = c_object_p + + library.LLVMGetPreviousInstruction.argtypes = [Instruction] + library.LLVMGetPreviousInstruction.restype = c_object_p + + library.LLVMGetInstructionOpcode.argtypes = [Instruction] + library.LLVMGetInstructionOpcode.restype = c_uint + def register_enumerations(): for name, value in enumerations.OpCodes: OpCode.register(name, value) +def initialize_llvm(): + c = Context.GetGlobalContext() + p = PassRegistry() + lib.LLVMInitializeCore(p) + lib.LLVMInitializeTransformUtils(p) + lib.LLVMInitializeScalarOpts(p) + lib.LLVMInitializeObjCARCOpts(p) + lib.LLVMInitializeVectorization(p) + lib.LLVMInitializeInstCombine(p) + lib.LLVMInitializeIPO(p) + lib.LLVMInitializeInstrumentation(p) + lib.LLVMInitializeAnalysis(p) + lib.LLVMInitializeIPA(p) + lib.LLVMInitializeCodeGen(p) + lib.LLVMInitializeTarget(p) + register_library(lib) register_enumerations() +initialize_llvm() diff --git a/bindings/python/llvm/disassembler.py b/bindings/python/llvm/disassembler.py index dcef9ac269058..f2df275bf4a09 100644 --- a/bindings/python/llvm/disassembler.py +++ b/bindings/python/llvm/disassembler.py @@ -10,7 +10,6 @@ from ctypes import CFUNCTYPE from ctypes import POINTER from ctypes import addressof -from ctypes import byref from ctypes import c_byte from ctypes import c_char_p from ctypes import c_int @@ -34,6 +33,29 @@ callbacks = {} # Constants for set_options Option_UseMarkup = 1 + + +_initialized = False +_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore'] +def _ensure_initialized(): + global _initialized + if not _initialized: + # Here one would want to call the functions + # LLVMInitializeAll{TargetInfo,TargetMC,Disassembler}s, but + # unfortunately they are only defined as static inline + # functions in the header files of llvm-c, so they don't exist + # as symbols in the shared library. + # So until that is fixed use this hack to initialize them all + for tgt in _targets: + for initializer in ("TargetInfo", "TargetMC", "Disassembler"): + try: + f = getattr(lib, "LLVMInitialize" + tgt + initializer) + except AttributeError: + continue + f() + _initialized = True + + class Disassembler(LLVMObject): """Represents a disassembler instance. @@ -48,9 +70,12 @@ class Disassembler(LLVMObject): The triple argument is the triple to create the disassembler for. This is something like 'i386-apple-darwin9'. """ + + _ensure_initialized() + ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0), callbacks['op_info'](0), callbacks['symbol_lookup'](0)) - if not ptr.contents: + if not ptr: raise Exception('Could not obtain disassembler for triple: %s' % triple) diff --git a/bindings/python/llvm/tests/base.py b/bindings/python/llvm/tests/base.py index ff9eb2fc14386..194f1a41192bf 100644 --- a/bindings/python/llvm/tests/base.py +++ b/bindings/python/llvm/tests/base.py @@ -30,3 +30,9 @@ class TestBase(unittest.TestCase): raise Exception('No suitable test binaries available!') get_test_binary.__test__ = False + + def get_test_file(self): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_file") + + def get_test_bc(self): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.bc") diff --git a/bindings/python/llvm/tests/test.bc b/bindings/python/llvm/tests/test.bc new file mode 100644 index 0000000000000..8d3d28fbc0db7 Binary files /dev/null and b/bindings/python/llvm/tests/test.bc differ diff --git a/bindings/python/llvm/tests/test_bitreader.py b/bindings/python/llvm/tests/test_bitreader.py new file mode 100644 index 0000000000000..d5850091a91f2 --- /dev/null +++ b/bindings/python/llvm/tests/test_bitreader.py @@ -0,0 +1,15 @@ +from .base import TestBase +from ..core import OpCode +from ..core import MemoryBuffer +from ..core import PassRegistry +from ..core import Context +from ..core import Module +from ..bit_reader import parse_bitcode + +class TestBitReader(TestBase): + + def test_parse_bitcode(self): + source = self.get_test_bc() + m = parse_bitcode(MemoryBuffer(filename=source)) + print m.target + print m.datalayout diff --git a/bindings/python/llvm/tests/test_core.py b/bindings/python/llvm/tests/test_core.py index 545abc826ea71..63f84c828bc8a 100644 --- a/bindings/python/llvm/tests/test_core.py +++ b/bindings/python/llvm/tests/test_core.py @@ -1,6 +1,10 @@ from .base import TestBase from ..core import OpCode from ..core import MemoryBuffer +from ..core import PassRegistry +from ..core import Context +from ..core import Module +from ..bit_reader import parse_bitcode class TestCore(TestBase): def test_opcode(self): @@ -13,7 +17,7 @@ class TestCore(TestBase): self.assertEqual(op, OpCode.Ret) def test_memory_buffer_create_from_file(self): - source = self.get_test_binary() + source = self.get_test_file() MemoryBuffer(filename=source) @@ -21,3 +25,106 @@ class TestCore(TestBase): with self.assertRaises(Exception): MemoryBuffer(filename="/hopefully/this/path/doesnt/exist") + def test_memory_buffer_len(self): + source = self.get_test_file() + m = MemoryBuffer(filename=source) + self.assertEqual(len(m), 50) + + def test_create_passregistry(self): + PassRegistry() + + def test_create_context(self): + Context.GetGlobalContext() + + def test_create_module_with_name(self): + # Make sure we can not create a module without a LLVMModuleRef. + with self.assertRaises(TypeError): + m = Module() + m = Module.CreateWithName("test-module") + + def test_module_getset_datalayout(self): + m = Module.CreateWithName("test-module") + dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" + m.datalayout = dl + self.assertEqual(m.datalayout, dl) + + def test_module_getset_target(self): + m = Module.CreateWithName("test-module") + target = "thumbv7-apple-ios5.0.0" + m.target = target + self.assertEqual(m.target, target) + + def test_module_print_module_to_file(self): + m = Module.CreateWithName("test") + dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" + m.datalayout = dl + target = "thumbv7-apple-ios5.0.0" + m.target = target + m.print_module_to_file("test2.ll") + + def test_module_function_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + functions = ["f", "f2", "f3", "f4", "f5", "f6", "g1", "g2", "h1", "h2", + "h3"] + # Forward + for f in m: + self.assertEqual(f.name, functions[i]) + f.dump() + i += 1 + # Backwards + for f in reversed(m): + i -= 1 + self.assertEqual(f.name, functions[i]) + f.dump() + + def test_function_basicblock_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + + bb_list = ['b1', 'b2', 'end'] + + f = m.first + while f.name != "f6": + f = f.next + + # Forward + for bb in f: + self.assertEqual(bb.name, bb_list[i]) + bb.dump() + i += 1 + + # Backwards + for bb in reversed(f): + i -= 1 + self.assertEqual(bb.name, bb_list[i]) + bb.dump() + + def test_basicblock_instruction_iteration(self): + m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc())) + i = 0 + + inst_list = [('arg1', OpCode.ExtractValue), + ('arg2', OpCode.ExtractValue), + ('', OpCode.Call), + ('', OpCode.Ret)] + + bb = m.first.first + + # Forward + for inst in bb: + self.assertEqual(inst.name, inst_list[i][0]) + self.assertEqual(inst.opcode, inst_list[i][1]) + for op in range(len(inst)): + o = inst.get_operand(op) + print o.name + o.dump() + inst.dump() + i += 1 + + # Backwards + for inst in reversed(bb): + i -= 1 + self.assertEqual(inst.name, inst_list[i][0]) + self.assertEqual(inst.opcode, inst_list[i][1]) + inst.dump() diff --git a/bindings/python/llvm/tests/test_disassembler.py b/bindings/python/llvm/tests/test_disassembler.py index 46d12f7056267..e960dc0ba9ca6 100644 --- a/bindings/python/llvm/tests/test_disassembler.py +++ b/bindings/python/llvm/tests/test_disassembler.py @@ -16,6 +16,10 @@ class TestDisassembler(TestBase): self.assertEqual(count, 3) self.assertEqual(s, '\tjcxz\t-127') + def test_nonexistant_triple(self): + with self.assertRaisesRegexp(Exception, "Could not obtain disassembler for triple"): + Disassembler("nonexistant-triple-raises") + def test_get_instructions(self): sequence = '\x67\xe3\x81\x01\xc7' # jcxz -127; addl %eax, %edi diff --git a/bindings/python/llvm/tests/test_file b/bindings/python/llvm/tests/test_file new file mode 100644 index 0000000000000..6c9b0385bd976 --- /dev/null +++ b/bindings/python/llvm/tests/test_file @@ -0,0 +1 @@ +I,"ìcAGðxq‘ÑÔ¹d«±ùà§vl¥À\»L>šg>`ö©ÿ©`‡wÉ© \ No newline at end of file diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 7f8c48d3aaaa3..dc991a23be075 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -35,37 +35,24 @@ function(check_type_exists type files 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_cxx(cxxabi.h HAVE_CXXABI_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(sanitizer/msan_interface.h HAVE_SANITIZER_MSAN_INTERFACE_H) -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) @@ -73,14 +60,12 @@ 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(zlib.h HAVE_ZLIB_H) check_include_file(fenv.h HAVE_FENV_H) check_symbol_exists(FE_ALL_EXCEPT "fenv.h" HAVE_DECL_FE_ALL_EXCEPT) @@ -112,6 +97,20 @@ if( NOT PURE_WINDOWS ) else() set(HAVE_LIBZ 0) endif() + if(LLVM_ENABLE_TERMINFO) + set(HAVE_TERMINFO 0) + foreach(library tinfo terminfo curses ncurses ncursesw) + string(TOUPPER ${library} library_suffix) + check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix}) + if(HAVE_TERMINFO_${library_suffix}) + set(HAVE_TERMINFO 1) + set(TERMINFO_LIBS "${library}") + break() + endif() + endforeach() + else() + set(HAVE_TERMINFO 0) + endif() endif() # function checks @@ -121,7 +120,6 @@ 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_symbol_exists(isatty unistd.h 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) @@ -136,6 +134,8 @@ check_symbol_exists(log10 math.h HAVE_LOG10) check_symbol_exists(exp math.h HAVE_EXP) check_symbol_exists(exp2 math.h HAVE_EXP2) check_symbol_exists(exp10 math.h HAVE_EXP10) +check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS) +check_symbol_exists(futimes sys/time.h HAVE_FUTIMES) if( HAVE_SETJMP_H ) check_symbol_exists(longjmp setjmp.h HAVE_LONGJMP) check_symbol_exists(setjmp setjmp.h HAVE_SETJMP) @@ -160,11 +160,7 @@ 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(posix_spawn spawn.h HAVE_POSIX_SPAWN) check_symbol_exists(pread unistd.h HAVE_PREAD) -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) +check_symbol_exists(realpath stdlib.h HAVE_REALPATH) check_symbol_exists(sbrk unistd.h HAVE_SBRK) check_symbol_exists(srand48 stdlib.h HAVE_RAND48_SRAND48) if( HAVE_RAND48_SRAND48 ) @@ -181,8 +177,6 @@ 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) @@ -206,13 +200,6 @@ if( PURE_WINDOWS ) 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) @@ -229,10 +216,7 @@ if( LLVM_USING_GLIBC ) add_llvm_definitions( -D_GNU_SOURCE ) endif() -set(headers "") -if (HAVE_SYS_TYPES_H) - set(headers ${headers} "sys/types.h") -endif() +set(headers "sys/types.h") if (HAVE_INTTYPES_H) set(headers ${headers} "inttypes.h") @@ -245,13 +229,13 @@ 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}) + + find_program(LLVM_PATH_${NAME} NAMES ${ARGV}) mark_as_advanced(LLVM_PATH_${NAME}) if(LLVM_PATH_${NAME}) set(HAVE_${NAME} 1 CACHE INTERNAL "Is ${name} available ?") @@ -268,7 +252,7 @@ llvm_find_program(neato) llvm_find_program(fdp) llvm_find_program(dot) llvm_find_program(dotty) -llvm_find_program(xdot.py) +llvm_find_program(xdot xdot.py) llvm_find_program(Graphviz) if( LLVM_ENABLE_FFI ) @@ -316,6 +300,20 @@ endif() find_package(LibXml2) if (LIBXML2_FOUND) set(CLANG_HAVE_LIBXML 1) + # When cross-compiling, liblzma is not detected as a dependency for libxml2, + # which makes linking c-index-test fail. But for native builds, all libraries + # are installed and checked by CMake before Makefiles are generated and everything + # works according to the plan. However, if a -llzma is added to native builds, + # an additional requirement on the static liblzma.a is required, but will not + # be checked by CMake, breaking native compilation. + # Since this is only pertinent to cross-compilations, and there's no way CMake + # can check for every foreign library on every OS, we add the dep and warn the dev. + if ( CMAKE_CROSSCOMPILING ) + if (NOT PC_LIBXML_VERSION VERSION_LESS "2.8.0") + message(STATUS "Adding LZMA as a dep to XML2 for cross-compilation, make sure liblzma.a is available.") + set(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} "-llzma") + endif () + endif () endif () include(CheckCXXCompilerFlag) @@ -384,6 +382,14 @@ else () message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") endif () +# If build targets includes "host", then replace with native architecture. +list(FIND LLVM_TARGETS_TO_BUILD "host" idx) +if( NOT idx LESS 0 ) + list(REMOVE_AT LLVM_TARGETS_TO_BUILD ${idx}) + list(APPEND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH}) + list(REMOVE_DUPLICATES LLVM_TARGETS_TO_BUILD) +endif() + list(FIND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH} NATIVE_ARCH_IDX) if (NATIVE_ARCH_IDX EQUAL -1) message(STATUS @@ -409,27 +415,26 @@ endif () if( MINGW ) set(HAVE_LIBIMAGEHLP 1) set(HAVE_LIBPSAPI 1) + set(HAVE_LIBSHELL32 1) # TODO: Check existence of libraries. # include(CheckLibraryExists) # CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP) endif( MINGW ) +if (NOT HAVE_STRTOLL) + # Use _strtoi64 if strtoll is not available. + check_symbol_exists(_strtoi64 stdlib.h have_strtoi64) + if (have_strtoi64) + set(HAVE_STRTOLL 1) + set(strtoll "_strtoi64") + set(strtoull "_strtoui64") + endif () +endif () + if( MSVC ) - set(error_t int) - 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 ) if( PURE_WINDOWS ) @@ -471,3 +476,25 @@ if (LLVM_ENABLE_ZLIB ) endif() set(LLVM_PREFIX ${CMAKE_INSTALL_PREFIX}) + +if (LLVM_ENABLE_DOXYGEN) + message(STATUS "Doxygen enabled.") + find_package(Doxygen) + + if (DOXYGEN_FOUND) + # If we find doxygen and we want to enable doxygen by default create a + # global aggregate doxygen target for generating llvm and any/all + # subprojects doxygen documentation. + if (LLVM_BUILD_DOCS) + add_custom_target(doxygen ALL) + endif() + + option(LLVM_DOXYGEN_EXTERNAL_SEARCH "Enable doxygen external search." OFF) + if (LLVM_DOXYGEN_EXTERNAL_SEARCH) + set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external searhc.") + set(LLVM_DOXYGEN_SEARCH_MAPPINGS "" CACHE STRING "Doxygen Search Mappings") + endif() + endif() +else() + message(STATUS "Doxygen disabled.") +endif() diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index f0b31ce653856..34e40172c96a1 100755 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -12,6 +12,11 @@ macro(add_llvm_library name) if( BUILD_SHARED_LIBS ) llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + if (MSVC) + set_target_properties(${name} + PROPERTIES + IMPORT_SUFFIX ".imp") + endif () endif() # Ensure that the system libraries always comes last on the @@ -21,9 +26,11 @@ macro(add_llvm_library name) if( EXCLUDE_FROM_ALL ) set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) else() - install(TARGETS ${name} - LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO") + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() endif() set_target_properties(${name} PROPERTIES FOLDER "Libraries") @@ -65,9 +72,11 @@ ${name} ignored.") if( EXCLUDE_FROM_ALL ) set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) else() - install(TARGETS ${name} - LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() endif() endif() @@ -91,14 +100,23 @@ macro(add_llvm_executable name) endmacro(add_llvm_executable name) +set (LLVM_TOOLCHAIN_TOOLS + llvm-ar + llvm-objdump + ) + 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) + + list(FIND LLVM_TOOLCHAIN_TOOLS ${name} LLVM_IS_${name}_TOOLCHAIN_TOOL) + if (LLVM_IS_${name}_TOOLCHAIN_TOOL GREATER -1 OR NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + if( LLVM_BUILD_TOOLS ) + install(TARGETS ${name} RUNTIME DESTINATION bin) + endif() endif() set_target_properties(${name} PROPERTIES FOLDER "Tools") endmacro(add_llvm_tool name) @@ -141,6 +159,7 @@ macro(add_llvm_external_project name) if("${add_llvm_external_dir}" STREQUAL "") set(add_llvm_external_dir ${name}) endif() + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") string(REPLACE "-" "_" nameUNDERSCORE ${name}) string(TOUPPER ${nameUNDERSCORE} nameUPPER) set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}" @@ -155,6 +174,34 @@ macro(add_llvm_external_project name) endif() endmacro(add_llvm_external_project) +macro(add_llvm_tool_subdirectory name) + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") + add_subdirectory(${name}) +endmacro(add_llvm_tool_subdirectory) + +macro(ignore_llvm_tool_subdirectory name) + list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") +endmacro(ignore_llvm_tool_subdirectory) + +function(add_llvm_implicit_external_projects) + set(list_of_implicit_subdirs "") + file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*") + foreach(dir ${sub-dirs}) + if(IS_DIRECTORY "${dir}") + list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore) + if( tool_subdir_ignore EQUAL -1 + AND EXISTS "${dir}/CMakeLists.txt") + get_filename_component(fn "${dir}" NAME) + list(APPEND list_of_implicit_subdirs "${fn}") + endif() + endif() + endforeach() + + foreach(external_proj ${list_of_implicit_subdirs}) + add_llvm_external_project("${external_proj}") + endforeach() +endfunction(add_llvm_implicit_external_projects) + # Generic support for adding a unittest. function(add_unittest test_suite test_name) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) @@ -191,7 +238,7 @@ function(add_unittest test_suite test_name) if (LLVM_COMPILER_IS_GCC_COMPATIBLE) set(target_compile_flags "${target_compile_flags} -fno-rtti") elseif (MSVC) - set(target_compile_flags "${target_compile_flags} /GR-") + llvm_replace_compiler_option(target_compile_flags "/GR" "/GR-") endif () if (SUPPORTS_NO_VARIADIC_MACROS_FLAG) @@ -249,6 +296,22 @@ function(configure_lit_site_cfg input output) set(HOST_OS ${CMAKE_SYSTEM_NAME}) set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + if (CLANG_ENABLE_ARCMT) + set(ENABLE_CLANG_ARCMT "1") + else() + set(ENABLE_CLANG_ARCMT "0") + endif() + if (CLANG_ENABLE_REWRITER) + set(ENABLE_CLANG_REWRITER "1") + else() + set(ENABLE_CLANG_REWRITER "0") + endif() + if (CLANG_ENABLE_STATIC_ANALYZER) + set(ENABLE_CLANG_STATIC_ANALYZER "1") + else() + set(ENABLE_CLANG_STATIC_ANALYZER "0") + endif() + configure_file(${input} ${output} @ONLY) endfunction() diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt index f51e9af8db0db..0253952caee8c 100644 --- a/cmake/modules/CMakeLists.txt +++ b/cmake/modules/CMakeLists.txt @@ -19,19 +19,21 @@ configure_file( ${llvm_cmake_builddir}/LLVMConfigVersion.cmake @ONLY) -install(FILES - ${llvm_cmake_builddir}/LLVMConfig.cmake - ${llvm_cmake_builddir}/LLVMConfigVersion.cmake - LLVM-Config.cmake - DESTINATION share/llvm/cmake) +if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(FILES + ${llvm_cmake_builddir}/LLVMConfig.cmake + ${llvm_cmake_builddir}/LLVMConfigVersion.cmake + LLVM-Config.cmake + DESTINATION share/llvm/cmake) -install(DIRECTORY . - DESTINATION share/llvm/cmake - FILES_MATCHING PATTERN *.cmake - PATTERN .svn EXCLUDE - PATTERN LLVMConfig.cmake EXCLUDE - PATTERN LLVMConfigVersion.cmake EXCLUDE - PATTERN LLVM-Config.cmake EXCLUDE - PATTERN GetHostTriple.cmake EXCLUDE - PATTERN VersionFromVCS.cmake EXCLUDE - PATTERN CheckAtomic.cmake EXCLUDE) + install(DIRECTORY . + DESTINATION share/llvm/cmake + FILES_MATCHING PATTERN *.cmake + PATTERN .svn EXCLUDE + PATTERN LLVMConfig.cmake EXCLUDE + PATTERN LLVMConfigVersion.cmake EXCLUDE + PATTERN LLVM-Config.cmake EXCLUDE + PATTERN GetHostTriple.cmake EXCLUDE + PATTERN VersionFromVCS.cmake EXCLUDE + PATTERN CheckAtomic.cmake EXCLUDE) +endif() diff --git a/cmake/modules/ChooseMSVCCRT.cmake b/cmake/modules/ChooseMSVCCRT.cmake index 6a2f426b26940..25ed9c71f1ab0 100644 --- a/cmake/modules/ChooseMSVCCRT.cmake +++ b/cmake/modules/ChooseMSVCCRT.cmake @@ -71,7 +71,7 @@ variables (LLVM_USE_CRT_DEBUG, etc) instead.") CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." FORCE) set_property(CACHE LLVM_USE_CRT_${build} - PROPERTY STRINGS "";${${MSVC_CRT}}) + PROPERTY STRINGS ;${${MSVC_CRT}}) endif(NOT LLVM_USE_CRT_${build}) endforeach(build_type) diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake index f8a017dcaef24..bb41a58df2dd4 100644 --- a/cmake/modules/HandleLLVMOptions.cmake +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -8,6 +8,8 @@ include(CheckCXXCompilerFlag) if( CMAKE_COMPILER_IS_GNUCXX ) set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) +elseif( MSVC ) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE OFF) elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) endif() @@ -17,13 +19,18 @@ if( LLVM_ENABLE_ASSERTIONS ) if( NOT MSVC ) add_definitions( -D_DEBUG ) endif() - # On Release builds cmake automatically defines NDEBUG, so we + # On non-Debug builds cmake automatically defines NDEBUG, so we # explicitly undefine it: - if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) add_definitions( -UNDEBUG ) # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines. - string (REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " - CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + set(REGEXP_NDEBUG "(^| )[/-]D *NDEBUG($| )") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + string (REGEX REPLACE "${REGEXP_NDEBUG}" " " + CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}") endif() else() if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) @@ -151,10 +158,25 @@ endif() if( MSVC ) include(ChooseMSVCCRT) - if( MSVC11 ) - add_llvm_definitions(-D_VARIADIC_MAX=10) + if( NOT (${CMAKE_VERSION} VERSION_LESS 2.8.11) ) + # set stack reserved size to ~10MB + # CMake previously automatically set this value for MSVC builds, but the + # behavior was changed in CMake 2.8.11 (Issue 12437) to use the MSVC default + # value (1 MB) which is not enough for us in tasks such as parsing recursive + # C++ templates in Clang. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000") endif() + if( MSVC10 ) + # MSVC 10 will complain about headers in the STL not being exported, but + # will not complain in MSVC 11. + add_llvm_definitions( + -wd4275 # Suppress 'An exported class was derived from a class that was not exported.' + ) + elseif( MSVC11 ) + add_llvm_definitions(-D_VARIADIC_MAX=10) + endif() + # Add definitions that make MSVC much less annoying. add_llvm_definitions( # For some reason MS wants to deprecate a bunch of standard functions... @@ -166,25 +188,18 @@ if( MSVC ) -D_SCL_SECURE_NO_WARNINGS # Disabled warnings. - -wd4065 # Suppress 'switch statement contains 'default' but no 'case' labels' -wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned' -wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored' - -wd4181 # Suppress 'qualifier applied to reference type; 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' - -wd4551 # Suppress 'function call missing argument list' -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' - -wd4722 # Suppress ''function' : destructor never returns, potential memory leak' -wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)' - + -wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception' + # Promoted warnings. -w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning. @@ -241,6 +256,10 @@ macro(append_common_sanitizer_flags) NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") add_flag_if_supported("-gline-tables-only") endif() + # Use -O1 even in debug mode, otherwise sanitizers slowdown is too large. + if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + add_flag_if_supported("-O1") + endif() endmacro() # Turn on sanitizers if necessary. @@ -263,6 +282,18 @@ if(LLVM_USE_SANITIZER) endif() endif() +# Turn on -gsplit-dwarf if requested +if(LLVM_USE_SPLIT_DWARF) + add_llvm_definitions("-gsplit-dwarf") +endif() + add_llvm_definitions( -D__STDC_CONSTANT_MACROS ) add_llvm_definitions( -D__STDC_FORMAT_MACROS ) add_llvm_definitions( -D__STDC_LIMIT_MACROS ) + +# clang doesn't print colored diagnostics when invoked from Ninja +if (UNIX AND + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND + CMAKE_GENERATOR STREQUAL "Ninja") + append("-fcolor-diagnostics" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +endif() diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 2ddc0b2bf89a3..e26fabd1c6f7f 100755 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -2,7 +2,7 @@ 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) + set(system_libs ${system_libs} imagehlp psapi shell32) elseif( CMAKE_HOST_UNIX ) if( HAVE_LIBRT ) set(system_libs ${system_libs} rt) @@ -10,6 +10,11 @@ function(get_system_libs return_var) if( HAVE_LIBDL ) set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) endif() + if(LLVM_ENABLE_TERMINFO) + if(HAVE_TERMINFO) + set(system_libs ${system_libs} ${TERMINFO_LIBS}) + endif() + endif() if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) set(system_libs ${system_libs} pthread) endif() diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index f0b8c14ec34df..68fe296924c59 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -20,6 +20,8 @@ set(TARGET_TRIPLE "@TARGET_TRIPLE@") set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) +set(LLVM_ENABLE_TERMINFO @LLVM_ENABLE_TERMINFO@) + set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) set(LLVM_ENABLE_ZLIB @LLVM_ENABLE_ZLIB@) @@ -28,6 +30,8 @@ set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@) set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) +set(HAVE_TERMINFO @HAVE_TERMINFO@) +set(TERMINFO_LIBS @TERMINFO_LIBS@) set(HAVE_LIBDL @HAVE_LIBDL@) set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@) set(HAVE_LIBZ @HAVE_LIBZ@) diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake index e3bdd9c704830..c17e67e478efb 100644 --- a/cmake/modules/TableGen.cmake +++ b/cmake/modules/TableGen.cmake @@ -66,7 +66,8 @@ if(CMAKE_CROSSCOMPILING) add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release - -DLLVM_BUILD_POLLY=OFF ${CMAKE_SOURCE_DIR} + -DLLVM_BUILD_POLLY=OFF + -G "${CMAKE_GENERATOR}" ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} DEPENDS ${CX_NATIVE_TG_DIR} COMMENT "Configuring native TableGen...") @@ -84,6 +85,16 @@ macro(add_tablegen target project) add_llvm_utility(${target} ${ARGN}) set(LLVM_LINK_COMPONENTS ${${target}_OLD_LLVM_LINK_COMPONENTS}) + # For Xcode builds, symlink bin/ to bin// so that + # a separately-configured Clang project can still find llvm-tblgen. + if (XCODE) + add_custom_target(${target}-top ALL + ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${target}${CMAKE_EXECUTABLE_SUFFIX} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}${CMAKE_EXECUTABLE_SUFFIX} + DEPENDS ${target}) + endif () + set(${project}_TABLEGEN "${target}" CACHE STRING "Native TableGen executable. Saves building one when cross-compiling.") @@ -117,7 +128,7 @@ macro(add_tablegen target project) endif() if( MINGW ) - target_link_libraries(${target} imagehlp psapi) + target_link_libraries(${target} imagehlp psapi shell32) if(CMAKE_SIZEOF_VOID_P MATCHES "8") set_target_properties(${target} PROPERTIES LINK_FLAGS -Wl,--stack,16777216) endif(CMAKE_SIZEOF_VOID_P MATCHES "8") @@ -126,5 +137,7 @@ macro(add_tablegen target project) target_link_libraries(${target} pthread) endif() - install(TARGETS ${target} RUNTIME DESTINATION bin) + if (${project} STREQUAL LLVM AND NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(TARGETS ${target} RUNTIME DESTINATION bin) + endif() endmacro() diff --git a/cmake/nsis_logo.bmp b/cmake/nsis_logo.bmp new file mode 100644 index 0000000000000..5fcb3cec19858 Binary files /dev/null and b/cmake/nsis_logo.bmp differ diff --git a/cmake/platforms/Android.cmake b/cmake/platforms/Android.cmake index 72849b16c7678..35df5ebd132f2 100644 --- a/cmake/platforms/Android.cmake +++ b/cmake/platforms/Android.cmake @@ -11,8 +11,15 @@ # make SET(CMAKE_SYSTEM_NAME Linux) -SET(CMAKE_C_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang) -SET(CMAKE_CXX_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang++) + +IF(NOT CMAKE_C_COMPILER) + SET(CMAKE_C_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang) +ENDIF() + +IF(NOT CMAKE_CXX_COMPILER) + SET(CMAKE_CXX_COMPILER ${CMAKE_BINARY_DIR}/../bin/clang++) +ENDIF() + SET(ANDROID "1" CACHE STRING "ANDROID" FORCE) SET(ANDROID_COMMON_FLAGS "-target arm-linux-androideabi --sysroot=${LLVM_ANDROID_TOOLCHAIN_DIR}/sysroot -B${LLVM_ANDROID_TOOLCHAIN_DIR} -mllvm -arm-enable-ehabi") diff --git a/configure b/configure index decbc409d836d..72e9b13304439 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.60 for LLVM 3.3. +# Generated by GNU Autoconf 2.60 for LLVM 3.4. # # Report bugs to . # @@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='LLVM' PACKAGE_TARNAME='llvm' -PACKAGE_VERSION='3.3' -PACKAGE_STRING='LLVM 3.3' +PACKAGE_VERSION='3.4' +PACKAGE_STRING='LLVM 3.4' PACKAGE_BUGREPORT='http://llvm.org/bugs/' ac_unique_file="lib/IR/Module.cpp" @@ -685,6 +685,7 @@ BUILD_CXX CVSBUILD ENABLE_LIBCPP ENABLE_CXX11 +ENABLE_SPLIT_DWARF ENABLE_CLANG_ARCMT ENABLE_CLANG_STATIC_ANALYZER ENABLE_CLANG_REWRITER @@ -708,7 +709,6 @@ ENABLE_PIC ENABLE_SHARED ENABLE_EMBED_STDCXX ENABLE_TIMESTAMPS -ENABLE_BACKTRACES TARGETS_TO_BUILD LLVM_ENUM_TARGETS LLVM_ENUM_ASM_PRINTERS @@ -743,7 +743,7 @@ TWOPI CIRCO GV DOTTY -XDOT_PY +XDOT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA @@ -786,7 +786,6 @@ SHLIBEXT SHLIBPATH_VAR LLVM_PREFIX LLVM_BINDIR -LLVM_LIBDIR LLVM_DATADIR LLVM_DOCSDIR LLVM_ETCDIR @@ -1331,7 +1330,7 @@ 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 3.3 to adapt to many kinds of systems. +\`configure' configures LLVM 3.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1397,7 +1396,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of LLVM 3.3:";; + short | recursive ) echo "Configuration of LLVM 3.4:";; esac cat <<\_ACEOF @@ -1407,6 +1406,7 @@ Optional Features: --enable-polly Use polly if available (default is YES) --enable-libcpp Use libc++ if available (default is NO) --enable-cxx11 Use c++11 if available (default is NO) + --enable-split-dwarf Use split-dwarf if available (default is NO) --enable-clang-arcmt Enable building of clang ARCMT (default is YES) --enable-clang-static-analyzer Enable building of clang Static Analyzer (default is @@ -1442,15 +1442,20 @@ Optional Features: (default is YES) --enable-backtraces Enable embedding backtraces on crash (default is YES) + --enable-crash-overrides + Enable crash handling overrides (default is YES) --enable-targets Build specific host targets: all or target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, arm, aarch64, mips, hexagon, - xcore, msp430, nvptx, systemz, and cpp (default=all) + xcore, msp430, nvptx, systemz, r600, and cpp + (default=all) --enable-experimental-targets Build experimental host targets: disable or target1,target2,... (default=disable) --enable-bindings Build specific language bindings: all,auto,none,{binding-name} (default=auto) + --enable-terminfo Query the terminfo database if available (default is + YES) --enable-libffi Check for the presence of libffi (default is NO) --enable-ltdl-install install libltdl @@ -1559,7 +1564,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -LLVM configure 3.3 +LLVM configure 3.4 generated by GNU Autoconf 2.60 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1575,7 +1580,7 @@ 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 3.3, which was +It was created by LLVM $as_me 3.4, which was generated by GNU Autoconf 2.60. Invocation command line was $ $0 $@ @@ -1935,7 +1940,7 @@ _ACEOF cat >>confdefs.h <<\_ACEOF -#define LLVM_VERSION_MINOR 3 +#define LLVM_VERSION_MINOR 4 _ACEOF @@ -1987,8 +1992,8 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;} fi fi -${CFLAGS=} -${CXXFLAGS=} +: ${CFLAGS=} +: ${CXXFLAGS=} ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -3824,11 +3829,16 @@ else llvm_cv_no_link_all_option="-Wl,-noall_load" llvm_cv_os_type="Minix" llvm_cv_platform_type="Unix" ;; - *-*-freebsd* | *-*-kfreebsd-gnu) + *-*-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" ;; + *-*-kfreebsd-gnu) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="GNU/kFreeBSD" + llvm_cv_platform_type="Unix" ;; *-*-openbsd*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -3925,8 +3935,10 @@ else llvm_cv_target_os_type="Darwin" ;; *-*-minix*) llvm_cv_target_os_type="Minix" ;; - *-*-freebsd* | *-*-kfreebsd-gnu) + *-*-freebsd*) llvm_cv_target_os_type="FreeBSD" ;; + *-*-kfreebsd-gnu) + llvm_cv_target_os_type="GNU/kFreeBSD" ;; *-*-openbsd*) llvm_cv_target_os_type="OpenBSD" ;; *-*-netbsd*) @@ -4024,7 +4036,6 @@ else xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; hexagon-*) llvm_cv_target_arch="Hexagon" ;; - mblaze-*) llvm_cv_target_arch="MBlaze" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -4059,7 +4070,6 @@ case $host in xcore-*) host_arch="XCore" ;; msp430-*) host_arch="MSP430" ;; hexagon-*) host_arch="Hexagon" ;; - mblaze-*) host_arch="MBlaze" ;; s390x-*) host_arch="SystemZ" ;; *) host_arch="Unknown" ;; esac @@ -5165,6 +5175,25 @@ echo "$as_me: error: Invalid setting for --enable-cxx11. Use \"yes\" or \"no\"" { (exit 1); exit 1; }; } ;; esac +# Check whether --enable-split-dwarf was given. +if test "${enable_split_dwarf+set}" = set; then + enableval=$enable_split_dwarf; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_SPLIT_DWARF=1 + ;; + no) ENABLE_SPLIT_DWARF=0 + ;; + default) ENABLE_SPLIT_DWARF=0 +;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-split-dwarf. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-split-dwarf. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + clang_arcmt="yes" # Check whether --enable-clang-arcmt was given. if test "${enable_clang_arcmt+set}" = set; then @@ -5196,8 +5225,15 @@ fi case "$enableval" in yes) ENABLE_CLANG_STATIC_ANALYZER=1 ;; - no) ENABLE_CLANG_STATIC_ANALYZER=0 - ;; + no) + if test ${clang_arcmt} != "no" ; then + { { echo "$as_me:$LINENO: error: Cannot enable clang ARC Migration Tool while disabling static analyzer." >&5 +echo "$as_me: error: Cannot enable clang ARC Migration Tool while disabling static analyzer." >&2;} + { (exit 1); exit 1; }; } + fi + ENABLE_CLANG_STATIC_ANALYZER=0 + + ;; default) ENABLE_CLANG_STATIC_ANALYZER=1 ;; *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-clang-static-analyzer. Use \"yes\" or \"no\"" >&5 @@ -5396,8 +5432,6 @@ else MSP430) TARGET_HAS_JIT=0 ;; Hexagon) TARGET_HAS_JIT=0 - ;; - MBlaze) TARGET_HAS_JIT=0 ;; NVPTX) TARGET_HAS_JIT=0 ;; @@ -5599,30 +5633,47 @@ cat >>confdefs.h <<_ACEOF _ACEOF - # Check whether --enable-backtraces was given. if test "${enable_backtraces+set}" = set; then - enableval=$enable_backtraces; + enableval=$enable_backtraces; case "$enableval" in + yes) llvm_cv_enable_backtraces="yes" ;; + no) llvm_cv_enable_backtraces="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac else - enableval=default + llvm_cv_enable_backtraces="yes" fi -case "$enableval" in - yes) ENABLE_BACKTRACES=1 - ;; - no) ENABLE_BACKTRACES=0 - ;; - default) ENABLE_BACKTRACES=1 - ;; - *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&5 -echo "$as_me: error: Invalid setting for --enable-backtraces. Use \"yes\" or \"no\"" >&2;} +if test "$llvm_cv_enable_backtraces" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_BACKTRACES 1 +_ACEOF + +fi + +# Check whether --enable-crash-overrides was given. +if test "${enable_crash_overrides+set}" = set; then + enableval=$enable_crash_overrides; case "$enableval" in + yes) llvm_cv_enable_crash_overrides="yes" ;; + no) llvm_cv_enable_crash_overrides="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-crash-overrides. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-crash-overrides. Use \"yes\" or \"no\"" >&2;} { (exit 1); exit 1; }; } ;; -esac + esac +else + llvm_cv_enable_crash_overrides="yes" +fi -cat >>confdefs.h <<_ACEOF -#define ENABLE_BACKTRACES $ENABLE_BACKTRACES +if test "$llvm_cv_enable_crash_overrides" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_CRASH_OVERRIDES 1 _ACEOF +fi TARGETS_TO_BUILD="" # Check whether --enable-targets was given. @@ -5636,7 +5687,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -5653,9 +5704,9 @@ case "$enableval" in msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; - mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + r600) TARGETS_TO_BUILD="R600 $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" ;; @@ -5664,7 +5715,6 @@ case "$enableval" in AArch64) TARGETS_TO_BUILD="AArch64 $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" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; @@ -5981,6 +6031,20 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# Check whether --enable-terminfo was given. +if test "${enable_terminfo+set}" = set; then + enableval=$enable_terminfo; case "$enableval" in + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_terminfo="yes" +fi + + # Check whether --enable-libffi was given. if test "${enable_libffi+set}" = set; then enableval=$enable_libffi; case "$enableval" in @@ -7196,16 +7260,18 @@ cat >>confdefs.h <<_ACEOF _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 +for ac_prog in xdot xdot.py +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_XDOT_PY+set}" = set; then +if test "${ac_cv_path_XDOT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - case $XDOT_PY in + case $XDOT in [\\/]* | ?:[\\/]*) - ac_cv_path_XDOT_PY="$XDOT_PY" # Let the user override the test with a path. + ac_cv_path_XDOT="$XDOT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -7215,7 +7281,7 @@ do 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" + ac_cv_path_XDOT="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -7223,32 +7289,35 @@ 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; } +XDOT=$ac_cv_path_XDOT +if test -n "$XDOT"; then + { echo "$as_me:$LINENO: result: $XDOT" >&5 +echo "${ECHO_T}$XDOT" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi -if test "$XDOT_PY" != "echo xdot.py" ; then + test -n "$XDOT" && break +done +test -n "$XDOT" || XDOT="echo xdot" + +if test "$XDOT" != "echo xdot" ; then cat >>confdefs.h <<\_ACEOF -#define HAVE_XDOT_PY 1 +#define HAVE_XDOT 1 _ACEOF if test "$llvm_cv_os_type" = "MingW" ; then - XDOT_PY=`echo $XDOT_PY | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + XDOT=`echo $XDOT | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` fi cat >>confdefs.h <<_ACEOF -#define LLVM_PATH_XDOT_PY "$XDOT_PY${EXEEXT}" +#define LLVM_PATH_XDOT "$XDOT${EXEEXT}" _ACEOF fi @@ -7961,8 +8030,8 @@ _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; } +{ echo "$as_me:$LINENO: checking for compiler -rdynamic option" >&5 +echo $ECHO_N "checking for compiler -rdynamic option... $ECHO_C" >&6; } if test "${llvm_cv_link_use_export_dynamic+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else @@ -7973,7 +8042,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu oldcflags="$CFLAGS" - CFLAGS="$CFLAGS -Wl,-export-dynamic" + CFLAGS="$CFLAGS -rdynamic" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -8756,9 +8825,7 @@ if test "${enable_ltdl_install+set}" = set; then fi - - -if test x"${enable_ltdl_install-no}" != xno; then + if test x"${enable_ltdl_install-no}" != xno; then INSTALL_LTDL_TRUE= INSTALL_LTDL_FALSE='#' else @@ -8766,9 +8833,7 @@ else INSTALL_LTDL_FALSE= fi - - -if test x"${enable_ltdl_convenience-no}" != xno; then + if test x"${enable_ltdl_convenience-no}" != xno; then CONVENIENCE_LTDL_TRUE= CONVENIENCE_LTDL_FALSE='#' else @@ -9396,24 +9461,6 @@ _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 @@ -10535,7 +10582,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&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 http://llvm.org/bugs/ ## -## ------------------------------------ ## -_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 +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 @@ -11744,452 +11613,7 @@ 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 @@ -12387,12 +11811,13 @@ fi { echo "$as_me:$LINENO: checking for python >= 2.5" >&5 echo $ECHO_N "checking for python >= 2.5... $ECHO_C" >&6; } -ac_python_version=`$PYTHON -c 'import sys; print sys.version.split()[0]'` +ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` -if test "$ac_python_version_major" -eq "2" \ - && test "$ac_python_version_minor" -ge "5" ; then +if test "$ac_python_version_major" -gt "2" || \ + (test "$ac_python_version_major" -eq "2" && \ + test "$ac_python_version_minor" -ge "5") ; then { echo "$as_me:$LINENO: result: $PYTHON ($ac_python_version)" >&5 echo "${ECHO_T}$PYTHON ($ac_python_version)" >&6; } else @@ -12486,22 +11911,103 @@ fi 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 +#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="-lm $LIBS" + LIBS="-limagehlp $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 "$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="-limagehlp $LIBS" +LIBS="-lpsapi $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -12552,37 +12058,37 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_lib_imagehlp_main=yes + ac_cv_lib_psapi_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lib_imagehlp_main=no + 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_imagehlp_main" >&5 -echo "${ECHO_T}$ac_cv_lib_imagehlp_main" >&6; } -if test $ac_cv_lib_imagehlp_main = yes; then +{ 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_LIBIMAGEHLP 1 +#define HAVE_LIBPSAPI 1 _ACEOF - LIBS="-limagehlp $LIBS" + LIBS="-lpsapi $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 "$as_me:$LINENO: checking for main in -lshell32" >&5 +echo $ECHO_N "checking for main in -lshell32... $ECHO_C" >&6; } +if test "${ac_cv_lib_shell32_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lpsapi $LIBS" +LIBS="-lshell32 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -12633,26 +12139,26 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_lib_psapi_main=yes + ac_cv_lib_shell32_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lib_psapi_main=no + ac_cv_lib_shell32_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 +{ echo "$as_me:$LINENO: result: $ac_cv_lib_shell32_main" >&5 +echo "${ECHO_T}$ac_cv_lib_shell32_main" >&6; } +if test $ac_cv_lib_shell32_main = yes; then cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPSAPI 1 +#define HAVE_LIBSHELL32 1 _ACEOF - LIBS="-lpsapi $LIBS" + LIBS="-lshell32 $LIBS" fi @@ -12865,6 +12371,112 @@ if test "$ac_res" != no; then fi +if test "$llvm_cv_enable_terminfo" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing setupterm" >&5 +echo $ECHO_N "checking for library containing setupterm... $ECHO_C" >&6; } +if test "${ac_cv_search_setupterm+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 setupterm (); +int +main () +{ +return setupterm (); + ; + return 0; +} +_ACEOF +for ac_lib in '' tinfo terminfo curses ncurses ncursesw; 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_setupterm=$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_setupterm+set}" = set; then + break +fi +done +if test "${ac_cv_search_setupterm+set}" = set; then + : +else + ac_cv_search_setupterm=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_setupterm" >&5 +echo "${ECHO_T}$ac_cv_search_setupterm" >&6; } +ac_res=$ac_cv_search_setupterm +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TERMINFO 1 +_ACEOF + +fi + +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; } @@ -15312,8 +14924,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - -for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h +for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.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 @@ -15656,8 +15267,7 @@ fi done - -for ac_header in utime.h windows.h +for ac_header in utime.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 @@ -16001,8 +15611,7 @@ done - -for ac_header in sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h +for ac_header in 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 @@ -18604,8 +18213,7 @@ done - -for ac_func in mktemp posix_spawn pread realpath sbrk setrlimit strdup +for ac_func in mktemp posix_spawn pread realpath sbrk setrlimit do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -19054,6 +18662,117 @@ _ACEOF fi done + + +for ac_func in futimes futimens +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 @@ -22306,7 +22025,6 @@ if test "${prefix}" = "NONE" ; then 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"; @@ -22324,7 +22042,6 @@ LLVM_CONFIGTIME=`date` - if test "${ENABLE_TIMESTAMPS}" = "0"; then LLVM_CONFIGTIME="(timestamp not enabled)" fi @@ -22340,11 +22057,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -cat >>confdefs.h <<_ACEOF -#define LLVM_LIBDIR "$LLVM_LIBDIR" -_ACEOF - - cat >>confdefs.h <<_ACEOF #define LLVM_DATADIR "$LLVM_DATADIR" _ACEOF @@ -22432,7 +22144,7 @@ echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found else # ocaml stdlib is outside our prefix; use libdir/ocaml - OCAML_LIBDIR=$LLVM_LIBDIR/ocaml + OCAML_LIBDIR=${prefix}/lib/ocaml fi fi @@ -22544,7 +22256,7 @@ fi if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then - RDYNAMIC="-Wl,-export-dynamic" + RDYNAMIC="-rdynamic" else RDYNAMIC="" fi @@ -22611,9 +22323,6 @@ 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" @@ -23036,7 +22745,7 @@ exec 6>&1 # 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 3.3, which was +This file was extended by LLVM $as_me 3.4, which was generated by GNU Autoconf 2.60. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23089,7 +22798,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -LLVM config.status 3.3 +LLVM config.status 3.4 configured by $0, generated by GNU Autoconf 2.60, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -23220,7 +22929,6 @@ do "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" ;; @@ -23374,6 +23082,7 @@ BUILD_CXX!$BUILD_CXX$ac_delim CVSBUILD!$CVSBUILD$ac_delim ENABLE_LIBCPP!$ENABLE_LIBCPP$ac_delim ENABLE_CXX11!$ENABLE_CXX11$ac_delim +ENABLE_SPLIT_DWARF!$ENABLE_SPLIT_DWARF$ac_delim ENABLE_CLANG_ARCMT!$ENABLE_CLANG_ARCMT$ac_delim ENABLE_CLANG_STATIC_ANALYZER!$ENABLE_CLANG_STATIC_ANALYZER$ac_delim ENABLE_CLANG_REWRITER!$ENABLE_CLANG_REWRITER$ac_delim @@ -23387,7 +23096,6 @@ DEBUG_RUNTIME!$DEBUG_RUNTIME$ac_delim DEBUG_SYMBOLS!$DEBUG_SYMBOLS$ac_delim KEEP_SYMBOLS!$KEEP_SYMBOLS$ac_delim JIT!$JIT$ac_delim -TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -23429,6 +23137,7 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim ENABLE_DOCS!$ENABLE_DOCS$ac_delim ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim LLVM_ENABLE_THREADS!$LLVM_ENABLE_THREADS$ac_delim @@ -23438,7 +23147,6 @@ 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 -ENABLE_BACKTRACES!$ENABLE_BACKTRACES$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 @@ -23473,7 +23181,7 @@ TWOPI!$TWOPI$ac_delim CIRCO!$CIRCO$ac_delim GV!$GV$ac_delim DOTTY!$DOTTY$ac_delim -XDOT_PY!$XDOT_PY$ac_delim +XDOT!$XDOT$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim @@ -23516,7 +23224,6 @@ 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 @@ -23526,6 +23233,7 @@ 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 @@ -23567,7 +23275,6 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF -OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim RPATH!$RPATH$ac_delim RDYNAMIC!$RDYNAMIC$ac_delim @@ -23576,7 +23283,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 7; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -23987,8 +23694,6 @@ echo "$as_me: executing $ac_file commands" >&6;} ${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` diff --git a/docs/Atomics.rst b/docs/Atomics.rst index 705d73fbaba43..1243f345483f4 100644 --- a/docs/Atomics.rst +++ b/docs/Atomics.rst @@ -211,7 +211,7 @@ Notes for code generation never stored. A normal load or store instruction is usually sufficient, but note that an unordered load or store cannot be split into multiple instructions (or an instruction which does multiple memory operations, like - ``LDRD`` on ARM). + ``LDRD`` on ARM without LPAE, or not naturally-aligned ``LDRD`` on LPAE ARM). Monotonic --------- diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index c83b6c1801cd4..d9d1df0b8e6fc 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -718,7 +718,7 @@ global variable. The operand fields are: MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -757,6 +757,9 @@ function. The operand fields are: * *unnamed_addr*: If present and non-zero, indicates that the function has ``unnamed_addr`` +* *prefix*: If non-zero, the value index of the prefix data for this function, + plus 1. + MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/CMake.rst b/docs/CMake.rst index 8459081fb8b31..c9fe538c9dfa1 100644 --- a/docs/CMake.rst +++ b/docs/CMake.rst @@ -87,7 +87,7 @@ names are case-sensitive. Example: .. code-block:: console - $ cmake -G "Visual Studio 9 2008" path/to/llvm/source/root + $ cmake -G "Visual Studio 10" 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 @@ -275,6 +275,11 @@ LLVM-specific variables Build with zlib to support compression/uncompression in LLVM tools. Defaults to ON. +**LLVM_USE_SANITIZER**:STRING + Define the sanitizer used to build LLVM binaries and tests. Possible values + are ``Address``, ``Memory`` and ``MemoryWithOrigins``. Defaults to empty + string. + Executing the test suite ======================== @@ -417,6 +422,5 @@ Microsoft Visual C++ **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. + when building with msbuild or Visual Studio. Only supported for the Visual + Studio 2010 CMake generator. 0 means use all processors. Default is 0. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000000000..8c49aa5e5f143 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,51 @@ + +if (DOXYGEN_FOUND) +if (LLVM_ENABLE_DOXYGEN) + set(abs_top_srcdir ${LLVM_MAIN_SRC_DIR}) + set(abs_top_builddir ${LLVM_BINARY_DIR}) + + if (HAVE_DOT) + set(DOT ${LLVM_PATH_DOT}) + endif() + + if (LLVM_DOXYGEN_EXTERNAL_SEARCH) + set(enable_searchengine "YES") + set(searchengine_url "${LLVM_DOXYGEN_SEARCHENGINE_URL}") + set(enable_server_based_search "YES") + set(enable_external_search "YES") + set(extra_search_mappings "${LLVM_DOXYGEN_SEARCH_MAPPINGS}") + else() + set(enable_searchengine "NO") + set(searchengine_url "") + set(enable_server_based_search "NO") + set(enable_external_search "NO") + set(extra_search_mappings "") + endif() + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxygen.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg @ONLY) + + set(abs_top_srcdir) + set(abs_top_builddir) + set(DOT) + set(enable_searchengine) + set(searchengine_url) + set(enable_server_based_search) + set(enable_external_search) + set(extra_search_mappings) + + add_custom_target(doxygen-llvm + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating llvm doxygen documentation." VERBATIM) + + if (LLVM_BUILD_DOCS) + add_dependencies(doxygen doxygen-llvm) + endif() + + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html + DESTINATION docs/html) + endif() +endif() +endif() diff --git a/docs/CodeGenerator.rst b/docs/CodeGenerator.rst index 10ca307b78699..c87a628672710 100644 --- a/docs/CodeGenerator.rst +++ b/docs/CodeGenerator.rst @@ -636,6 +636,18 @@ 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. +For target specific directives, the MCStreamer has a MCTargetStreamer instance. +Each target that needs it defines a class that inherits from it and is a lot +like MCStreamer itself: It has one method per directive and two classes that +inherit from it, a target object streamer and a target asm streamer. The target +asm streamer just prints it (``emitFnStart -> .fnstrart``), and the object +streamer implement the assembler logic for it. + +To make llvm use these classes, the target initialization must call +TargetRegistry::RegisterAsmStreamer and TargetRegistry::RegisterMCObjectStreamer +passing callbacks that allocate the corresponding target streamer and pass it +to createAsmStreamer or to the appropriate object streamer constructor. + The ``MCContext`` class ----------------------- @@ -1614,7 +1626,7 @@ Implementing a Native Assembler =============================== 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. +compiler backend, LLVM also fully supports building a native assembler. 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 @@ -1788,7 +1800,6 @@ Here is the table: :raw-html:`Feature` :raw-html:`ARM` :raw-html:`Hexagon` -:raw-html:`MBlaze` :raw-html:`MSP430` :raw-html:`Mips` :raw-html:`NVPTX` @@ -1803,7 +1814,6 @@ Here is the table: :raw-html:`is generally reliable` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1818,7 +1828,6 @@ Here is the table: :raw-html:`assembly parser` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1833,12 +1842,11 @@ Here is the table: :raw-html:`disassembler` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` -:raw-html:` ` +:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1848,7 +1856,6 @@ Here is the table: :raw-html:`inline asm` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1863,7 +1870,6 @@ Here is the table: :raw-html:`jit` :raw-html:`* ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1878,7 +1884,6 @@ Here is the table: :raw-html:`.o file writing` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1893,7 +1898,6 @@ Here is the table: :raw-html:`tail calls` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` @@ -1908,7 +1912,6 @@ Here is the table: :raw-html:`segmented stacks` :raw-html:` ` :raw-html:` ` -:raw-html:` ` :raw-html:` ` :raw-html:` ` :raw-html:` ` diff --git a/docs/CodingStandards.rst b/docs/CodingStandards.rst index 4d66ad7574354..9418680edc74a 100644 --- a/docs/CodingStandards.rst +++ b/docs/CodingStandards.rst @@ -796,7 +796,9 @@ In general, names should be in camel case (e.g. ``TextFileReader`` and 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()``). +``push_back()``, and ``empty()``). Classes that provide multiple +iterators should add a singular prefix to ``begin()`` and ``end()`` +(e.g. ``global_begin()`` and ``use_begin()``). Here are some examples of good and bad names: diff --git a/docs/CommandGuide/FileCheck.rst b/docs/CommandGuide/FileCheck.rst index fce63ba688cc3..5a60d60ae3df0 100644 --- a/docs/CommandGuide/FileCheck.rst +++ b/docs/CommandGuide/FileCheck.rst @@ -18,7 +18,8 @@ using :program:`grep`, but it is optimized for matching multiple different inputs in one file in a specific order. The ``match-filename`` file specifies the file that contains the patterns to -match. The file to verify is always read from standard input. +match. The file to verify is read from standard input unless the +:option:`--input-file` option is used. OPTIONS ------- @@ -29,11 +30,13 @@ OPTIONS .. option:: --check-prefix prefix - FileCheck searches the contents of ``match-filename`` 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 :option:`--check-prefix` argument allows you - to specify a specific prefix to match. + FileCheck searches the contents of ``match-filename`` 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 + :option:`--check-prefix` argument allows you to specify one or more + prefixes to match. Multiple prefixes are useful for tests which might + change for different run options, but most lines remain the same. .. option:: --input-file filename @@ -44,7 +47,7 @@ OPTIONS By default, FileCheck canonicalizes input horizontal whitespace (spaces and tabs) which causes it to ignore these differences (a space will match a tab). The :option:`--strict-whitespace` argument disables this behavior. End-of-line - sequences are canonicalized to UNIX-style '\n' in all modes. + sequences are canonicalized to UNIX-style ``\n`` in all modes. .. option:: -version @@ -194,6 +197,134 @@ can be used: ; CHECK: ret i8 } +The "CHECK-DAG:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If it's necessary to match strings that don't occur in a strictly sequential +order, "``CHECK-DAG:``" could be used to verify them between two matches (or +before the first match, or after the last match). For example, clang emits +vtable globals in reverse order. Using ``CHECK-DAG:``, we can keep the checks +in the natural order: + +.. code-block:: c++ + + // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + + struct Foo { virtual void method(); }; + Foo f; // emit vtable + // CHECK-DAG: @_ZTV3Foo = + + struct Bar { virtual void method(); }; + Bar b; + // CHECK-DAG: @_ZTV3Bar = + +``CHECK-NOT:`` directives could be mixed with ``CHECK-DAG:`` directives to +exclude strings between the surrounding ``CHECK-DAG:`` directives. As a result, +the surrounding ``CHECK-DAG:`` directives cannot be reordered, i.e. all +occurrences matching ``CHECK-DAG:`` before ``CHECK-NOT:`` must not fall behind +occurrences matching ``CHECK-DAG:`` after ``CHECK-NOT:``. For example, + +.. code-block:: llvm + + ; CHECK-DAG: BEFORE + ; CHECK-NOT: NOT + ; CHECK-DAG: AFTER + +This case will reject input strings where ``BEFORE`` occurs after ``AFTER``. + +With captured variables, ``CHECK-DAG:`` is able to match valid topological +orderings of a DAG with edges from the definition of a variable to its use. +It's useful, e.g., when your test cases need to match different output +sequences from the instruction scheduler. For example, + +.. code-block:: llvm + + ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2 + ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4 + ; CHECK: mul r5, [[REG1]], [[REG2]] + +In this case, any order of that two ``add`` instructions will be allowed. + +If you are defining `and` using variables in the same ``CHECK-DAG:`` block, +be aware that the definition rule can match `after` its use. + +So, for instance, the code below will pass: + +.. code-block:: llvm + + ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] + ; CHECK-DAG: vmov.32 [[REG2]][1] + vmov.32 d0[1] + vmov.32 d0[0] + +While this other code, will not: + +.. code-block:: llvm + + ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] + ; CHECK-DAG: vmov.32 [[REG2]][1] + vmov.32 d1[1] + vmov.32 d0[0] + +While this can be very useful, it's also dangerous, because in the case of +register sequence, you must have a strong order (read before write, copy before +use, etc). If the definition your test is looking for doesn't match (because +of a bug in the compiler), it may match further away from the use, and mask +real bugs away. + +In those cases, to enforce the order, use a non-DAG directive between DAG-blocks. + +The "CHECK-LABEL:" directive +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes in a file containing multiple tests divided into logical blocks, one +or more ``CHECK:`` directives may inadvertently succeed by matching lines in a +later block. While an error will usually eventually be generated, the check +flagged as causing the error may not actually bear any relationship to the +actual source of the problem. + +In order to produce better error messages in these cases, the "``CHECK-LABEL:``" +directive can be used. It is treated identically to a normal ``CHECK`` +directive except that FileCheck makes an additional assumption that a line +matched by the directive cannot also be matched by any other check present in +``match-filename``; this is intended to be used for lines containing labels or +other unique identifiers. Conceptually, the presence of ``CHECK-LABEL`` divides +the input stream into separate blocks, each of which is processed independently, +preventing a ``CHECK:`` directive in one block matching a line in another block. +For example, + +.. code-block:: llvm + + define %struct.C* @C_ctor_base(%struct.C* %this, i32 %x) { + entry: + ; CHECK-LABEL: C_ctor_base: + ; CHECK: mov [[SAVETHIS:r[0-9]+]], r0 + ; CHECK: bl A_ctor_base + ; CHECK: mov r0, [[SAVETHIS]] + %0 = bitcast %struct.C* %this to %struct.A* + %call = tail call %struct.A* @A_ctor_base(%struct.A* %0) + %1 = bitcast %struct.C* %this to %struct.B* + %call2 = tail call %struct.B* @B_ctor_base(%struct.B* %1, i32 %x) + ret %struct.C* %this + } + + define %struct.D* @D_ctor_base(%struct.D* %this, i32 %x) { + entry: + ; CHECK-LABEL: D_ctor_base: + +The use of ``CHECK-LABEL:`` directives in this case ensures that the three +``CHECK:`` directives only accept lines corresponding to the body of the +``@C_ctor_base`` function, even if the patterns match lines found later in +the file. Furthermore, if one of these three ``CHECK:`` directives fail, +FileCheck will recover by continuing to the next block, allowing multiple test +failures to be detected in a single invocation. + +There is no requirement that ``CHECK-LABEL:`` directives contain strings that +correspond to actual syntactic labels in a source or output language: they must +simply uniquely match a single line in the file being verified. + +``CHECK-LABEL:`` directives cannot contain variable definitions or uses. + FileCheck Pattern Matching Syntax ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst index b3b4bc389edda..d50542ddc9dad 100644 --- a/docs/CommandGuide/index.rst +++ b/docs/CommandGuide/index.rst @@ -21,7 +21,6 @@ Basic Commands lli llvm-link llvm-ar - llvm-ranlib llvm-nm llvm-prof llvm-config diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst index 40c7646260a44..4d84be63dff24 100644 --- a/docs/CommandGuide/lit.rst +++ b/docs/CommandGuide/lit.rst @@ -149,12 +149,11 @@ ADDITIONAL OPTIONS .. option:: --show-suites - List the discovered test suites as part of the standard output. + List the discovered test suites and exit. -.. option:: --repeat=N +.. option:: --show-tests - Run each test ``N`` times. Currently this is primarily useful for timing - tests, other results are not collated in any reasonable fashion. + List all of the the discovered tests and exit. EXIT STATUS ----------- @@ -283,7 +282,7 @@ executed, two important global variables are predefined: discover and run tests in the test suite. Generally this will be a builtin test format available from the *lit.formats* module. - **test_src_root** The filesystem path to the test suite root. For out-of-dir + **test_source_root** The filesystem path to the test suite root. For out-of-dir builds this is the directory that will be scanned for tests. **test_exec_root** For out-of-dir builds, the path to the test suite root inside @@ -316,11 +315,15 @@ executed, two important global variables are predefined: *on_clone* function will generally modify), and (3) the test path to the new directory being scanned. + **pipefail** Normally a test using a shell pipe fails if any of the commands + on the pipe fail. If this is not desired, setting this variable to false + makes the test fail only if the last command in the pipe fails. + TEST DISCOVERY ~~~~~~~~~~~~~~ Once test suites are located, :program:`lit` recursively traverses the source -directory (following *test_src_root*) looking for tests. When :program:`lit` +directory (following *test_source_root*) looking for tests. When :program:`lit` enters a sub-directory, it first checks to see if a nested 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 diff --git a/docs/CommandGuide/llc.rst b/docs/CommandGuide/llc.rst index e6a59767aaff9..02ad798c8b66f 100644 --- a/docs/CommandGuide/llc.rst +++ b/docs/CommandGuide/llc.rst @@ -141,24 +141,24 @@ Tuning/Configuration Options .. option:: --regalloc= - Specify the register allocator to use. The default ``allocator`` is *local*. + Specify the register allocator to use. Valid register allocators are: - *simple* + *basic* - Very simple "always spill" register allocator + Basic register allocator. - *local* + *fast* - Local register allocator + Fast register allocator. It is the default for unoptimized code. - *linearscan* + *greedy* - Linear scan global register allocator + Greedy register allocator. It is the default for optimized code. - *iterativescan* + *pbqp* - Iterative scan global register allocator + Register allocator based on 'Partitioned Boolean Quadratic Programming'. .. option:: --spiller= diff --git a/docs/CommandGuide/llvm-ar.rst b/docs/CommandGuide/llvm-ar.rst index 8ff4192a50076..d3ee993f738eb 100644 --- a/docs/CommandGuide/llvm-ar.rst +++ b/docs/CommandGuide/llvm-ar.rst @@ -21,64 +21,24 @@ LLVM program. However, the archive can contain any kind of file. By default, only the symbol table needs to be consulted, not each individual file member of the archive. -The **llvm-ar** command can be used to *read* both SVR4 and BSD style archive -files. However, it cannot be used to write them. While the **llvm-ar** command -produces files that are *almost* identical to the format used by other ``ar`` -implementations, it has two significant departures in order to make the -archive appropriate for LLVM. The first departure is that **llvm-ar** 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 **llvm-ar** usually won't be readable or editable with any -``ar`` implementation or useful for linking. Using the ``f`` modifier to flatten -file names will make the archive readable by other ``ar`` implementations -but not for linking because the symbol table format for LLVM is unique. If an +The **llvm-ar** command can be used to *read* SVR4, GNU and BSD style archive +files. However, right now it can only write in the GNU format. If an SVR4 or BSD style archive is used with the ``r`` (replace) or ``q`` (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. +update) operations, the archive will be reconstructed in GNU format. Here's where **llvm-ar** departs from previous ``ar`` implementations: *Symbol Table* - Since **llvm-ar** 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. - + Since **llvm-ar** supports bitcode files. The symbol table it creates + is in GNU format and includes both native and bitcode files. *Long Paths* - Some ``ar`` implementations (SVR4) use a separate file member to record long - path names (> 15 characters). **llvm-ar** 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. - - - -*Directory Recursion* - - Most ``ar`` implementations do not recurse through directories but simply - ignore directories if they are presented to the program in the *files* - option. **llvm-ar**, however, can recurse through directory structures and - add all the files under a directory, if requested. - - - -*TOC Verbose Output* - - When **llvm-ar** prints out the verbose table of contents (``tv`` 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 'B' means - the file is an LLVM bitcode file. An 'S' means the file is the symbol table. - + Currently **llvm-ar** can read GNU and BSD long file names, but only writes + archives with the GNU format. @@ -124,20 +84,19 @@ m[abi] -p[k] +p - Print files to the standard output. The *k* modifier applies to this - operation. This operation simply prints the *files* indicated to the - standard output. If no *files* are specified, the entire archive is printed. - Printing bitcode files is ill-advised as they might confuse your terminal - settings. The *p* operation never modifies the archive. + Print files to the standard output. This operation simply prints the + *files* indicated to the standard output. If no *files* are + specified, the entire archive is printed. Printing bitcode files is + ill-advised as they might confuse your terminal settings. The *p* + operation never modifies the archive. -q[Rf] +q - Quickly append files to the end of the archive. The *R*, and *f* - modifiers apply to this operation. This operation quickly adds the + Quickly append files to the end of the archive. This operation quickly adds the *files* to the archive without checking for duplicates that should be removed first. If no *files* are specified, the archive is not modified. Because of the way that **llvm-ar** constructs the archive file, its dubious @@ -145,9 +104,9 @@ q[Rf] -r[Rabfu] +r[abu] - Replace or insert file members. The *R*, *a*, *b*, *f*, and *u* + Replace or insert file members. The *a*, *b*, and *u* modifiers apply to this operation. This operation will replace existing *files* or insert them at the end of the archive if they do not exist. If no *files* are specified, the archive is not modified. @@ -201,37 +160,12 @@ section (above) to determine which modifiers are applicable to which operations. -[f] - - Normally, **llvm-ar** 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 ``ar`` but may also - thwart correct extraction of the files (duplicates may overwrite). If used with - the *R* option, the directory recursion will be performed but the file names - will all be flattened to simple file names. - - - [i] A synonym for the *b* option. -[k] - - Normally, **llvm-ar** will not print the contents of bitcode files when the - *p* operation is used. This modifier defeats the default and allows the - bitcode members to be printed. - - - -[N] - - This option is ignored by **llvm-ar** but provided for compatibility. - - - [o] When extracting files, this option will cause **llvm-ar** to preserve the @@ -239,22 +173,6 @@ section (above) to determine which modifiers are applicable to which operations. -[P] - - use full path names when matching - - - -[R] - - This modifier instructions the *r* option to recursively process directories. - Without *R*, directories are ignored and only those *files* that refer to - files will be added to the archive. When *R* is used, any directories specified - with *files* 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. - - - [u] When replacing existing files in the archive, only replace those files that have @@ -283,8 +201,7 @@ The modifiers below may be applied to any operation. 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 - llvm-ranlib|llvm-ranlib which also creates the symbol table. + bitcode files in the archive. @@ -401,14 +318,6 @@ fmag - char[2] utility in identifying archive files that have been corrupted. - -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: - - offset - vbr encoded 32-bit integer The offset item provides the offset into the archive file where the bitcode @@ -455,4 +364,4 @@ SEE ALSO -------- -llvm-ranlib|llvm-ranlib, ar(1) +ar(1) diff --git a/docs/CommandGuide/llvm-extract.rst b/docs/CommandGuide/llvm-extract.rst index d569e35729eba..d0e9c1c255abd 100644 --- a/docs/CommandGuide/llvm-extract.rst +++ b/docs/CommandGuide/llvm-extract.rst @@ -1,104 +1,79 @@ llvm-extract - extract a function from an LLVM module ===================================================== - SYNOPSIS -------- - -**llvm-extract** [*options*] **--func** *function-name* [*filename*] - +:program:`llvm-extract` [*options*] **--func** *function-name* [*filename*] DESCRIPTION ----------- - -The **llvm-extract** command takes the name of a function and extracts it from -the specified LLVM bitcode file. It is primarily used as a debugging tool to -reduce test cases from larger programs that are triggering a bug. +The :program:`llvm-extract` command takes the name of a function and extracts +it from the specified LLVM bitcode file. It is primarily used as a debugging +tool to reduce test cases from larger programs that are triggering a bug. In addition to extracting the bitcode of the specified function, -**llvm-extract** will also remove unreachable global variables, prototypes, and -unused types. - -The **llvm-extract** command reads its input from standard input if filename is -omitted or if filename is -. The output is always written to standard output, -unless the **-o** option is specified (see below). +:program:`llvm-extract` will also remove unreachable global variables, +prototypes, and unused types. +The :program:`llvm-extract` command reads its input from standard input if +filename is omitted or if filename is ``-``. The output is always written to +standard output, unless the **-o** option is specified (see below). OPTIONS ------- - - **-f** - Enable binary output on terminals. Normally, **llvm-extract** will refuse to - write raw bitcode output if the output stream is a terminal. With this option, - **llvm-extract** will write raw bitcode regardless of the output device. - - + Enable binary output on terminals. Normally, :program:`llvm-extract` will + refuse to write raw bitcode output if the output stream is a terminal. With + this option, :program:`llvm-extract` will write raw bitcode regardless of the + output device. **--func** *function-name* - Extract the function named *function-name* from the LLVM bitcode. May be + Extract the function named *function-name* from the LLVM bitcode. May be specified multiple times to extract multiple functions at once. - - **--rfunc** *function-regular-expr* Extract the function(s) matching *function-regular-expr* from the LLVM bitcode. All functions matching the regular expression will be extracted. May be specified multiple times. - - **--glob** *global-name* - Extract the global variable named *global-name* from the LLVM bitcode. May be + Extract the global variable named *global-name* from the LLVM bitcode. May be specified multiple times to extract multiple global variables at once. - - **--rglob** *glob-regular-expr* Extract the global variable(s) matching *global-regular-expr* from the LLVM - bitcode. All global variables matching the regular expression will be extracted. - May be specified multiple times. - - + bitcode. All global variables matching the regular expression will be + extracted. May be specified multiple times. **-help** Print a summary of command line options. - - **-o** *filename* Specify the output filename. If filename is "-" (the default), then - **llvm-extract** sends its output to standard output. - - + :program:`llvm-extract` sends its output to standard output. **-S** Write output in LLVM intermediate language (instead of bitcode). - - - EXIT STATUS ----------- - -If **llvm-extract** succeeds, it will exit with 0. Otherwise, if an error +If :program:`llvm-extract` succeeds, it will exit with 0. Otherwise, if an error occurs, it will exit with a non-zero value. - SEE ALSO -------- +bugpoint -bugpoint|bugpoint diff --git a/docs/CommandGuide/llvm-nm.rst b/docs/CommandGuide/llvm-nm.rst index cbc7af207592c..83d9fbaf9e8cc 100644 --- a/docs/CommandGuide/llvm-nm.rst +++ b/docs/CommandGuide/llvm-nm.rst @@ -1,189 +1,146 @@ llvm-nm - list LLVM bitcode and object file's symbol table ========================================================== - SYNOPSIS -------- - :program:`llvm-nm` [*options*] [*filenames...*] - DESCRIPTION ----------- - The :program:`llvm-nm` utility lists the names of symbols from the LLVM bitcode files, object files, or :program:`ar` archives containing them, named on the -command line. Each symbol is listed along with some simple information about its -provenance. If no file name is specified, or *-* is used as a file name, +command line. Each symbol is listed along with some simple information about +its provenance. If no file name is specified, or *-* is used as a file name, :program:`llvm-nm` will process a file on its standard input stream. :program:`llvm-nm`'s default output format is the traditional BSD :program:`nm` -output format. Each such output record consists of an (optional) 8-digit +output format. Each such output record consists of an (optional) 8-digit hexadecimal address, followed by a type code character, followed by a name, for -each symbol. One record is printed per line; fields are separated by spaces. +each symbol. One record is printed per line; fields are separated by spaces. When the address is omitted, it is replaced by 8 spaces. Type code characters currently supported, and their meanings, are as follows: - U Named object is referenced but undefined in this bitcode file - - C Common (multiple definitions link together into one def) - - W Weak reference (multiple definitions link together into zero or one definitions) - - t Local function (text) object - - T Global function (text) object - - d Local data object - - D Global data object - - ? Something unrecognizable - - Because LLVM bitcode files typically contain objects that are not considered to have addresses until they are linked into an executable image or dynamically compiled "just-in-time", :program:`llvm-nm` does not print an address for any -symbol in a LLVM bitcode file, even symbols which are defined in the bitcode +symbol in an LLVM bitcode file, even symbols which are defined in the bitcode file. - OPTIONS ------- - .. program:: llvm-nm - .. option:: -B (default) - Use BSD output format. Alias for :option:`--format=bsd`. - + Use BSD output format. Alias for :option:`--format=bsd`. .. option:: -P - Use POSIX.2 output format. Alias for :option:`--format=posix`. - + Use POSIX.2 output format. Alias for :option:`--format=posix`. .. option:: --debug-syms, -a Show all symbols, even debugger only. - .. option:: --defined-only Print only symbols defined in this file (as opposed to symbols which may be referenced by objects in this file, but not defined in this file.) - .. option:: --dynamic, -D Display dynamic symbols instead of normal symbols. - .. option:: --extern-only, -g Print only symbols whose definitions are external; that is, accessible from other files. - .. option:: --format=format, -f format - Select an output format; *format* may be *sysv*, *posix*, or *bsd*. The default + Select an output format; *format* may be *sysv*, *posix*, or *bsd*. The default is *bsd*. - .. option:: -help Print a summary of command-line options and their meanings. - .. option:: --no-sort, -p Shows symbols in order encountered. - .. option:: --numeric-sort, -n, -v Sort symbols by address. - .. option:: --print-file-name, -A, -o Precede each symbol with the file it came from. - .. option:: --print-size, -S Show symbol size instead of address. - .. option:: --size-sort Sort symbols by size. - .. option:: --undefined-only, -u Print only symbols referenced but not defined in this file. - BUGS ---- - * :program:`llvm-nm` cannot demangle C++ mangled names, like GNU :program:`nm` can. * :program:`llvm-nm` does not support the full set of arguments that GNU :program:`nm` does. - EXIT STATUS ----------- - :program:`llvm-nm` exits with an exit code of zero. - SEE ALSO -------- - -llvm-dis|llvm-dis, ar(1), nm(1) +llvm-dis, ar(1), nm(1) diff --git a/docs/CommandGuide/llvm-ranlib.rst b/docs/CommandGuide/llvm-ranlib.rst deleted file mode 100644 index 6658818f41e56..0000000000000 --- a/docs/CommandGuide/llvm-ranlib.rst +++ /dev/null @@ -1,61 +0,0 @@ -llvm-ranlib - Generate index for LLVM archive -============================================= - - -SYNOPSIS --------- - - -**llvm-ranlib** [--version] [-help] - - -DESCRIPTION ------------ - - -The **llvm-ranlib** command is similar to the common Unix utility, ``ranlib``. It -adds or updates the symbol table in an LLVM archive file. Note that using the -**llvm-ar** modifier *s* is usually more efficient than running **llvm-ranlib** -which is only provided only for completness and compatibility. Unlike other -implementations of ``ranlib``, **llvm-ranlib** indexes LLVM bitcode files, not -native object modules. You can list the contents of the symbol table with the -``llvm-nm -s`` command. - - -OPTIONS -------- - - - -*archive-file* - - Specifies the archive-file to which the symbol table is added or updated. - - - -*--version* - - Print the version of **llvm-ranlib** and exit without building a symbol table. - - - -*-help* - - Print usage help for **llvm-ranlib** and exit without building a symbol table. - - - - -EXIT STATUS ------------ - - -If **llvm-ranlib** succeeds, it will exit with 0. If an error occurs, a non-zero -exit code will be returned. - - -SEE ALSO --------- - - -llvm-ar|llvm-ar, ranlib(1) diff --git a/docs/CommandGuide/llvm-symbolizer.rst b/docs/CommandGuide/llvm-symbolizer.rst index 73babb1e5c559..e03be9b19876d 100644 --- a/docs/CommandGuide/llvm-symbolizer.rst +++ b/docs/CommandGuide/llvm-symbolizer.rst @@ -22,6 +22,8 @@ EXAMPLE a.out 0x4004f4 /tmp/b.out 0x400528 /tmp/c.so 0x710 + /tmp/mach_universal_binary:i386 0x1f84 + /tmp/mach_universal_binary:x86_64 0x100000f24 $ llvm-symbolizer < addr.txt main /tmp/a.cc:4 @@ -38,6 +40,12 @@ EXAMPLE main /tmp/source.cc:8 + _main + /tmp/source_i386.cc:8 + + _main + /tmp/source_x86_64.cc:8 + OPTIONS ------- @@ -59,6 +67,14 @@ OPTIONS If a source code location is in an inlined function, prints all the inlnied frames. Defaults to true. +.. option:: -default-arch + + If a binary contains object files for multiple architectures (e.g. it is a + Mach-O universal binary), symbolize the object file for a given architecture. + You can also specify architecture by writing ``binary_name:arch_name`` in the + input (see example above). If architecture is not specified in either way, + address will not be symbolized. Defaults to empty string. + EXIT STATUS ----------- diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst index 9b77a9890826c..4c84d23297b45 100644 --- a/docs/CommandLine.rst +++ b/docs/CommandLine.rst @@ -925,12 +925,13 @@ This section describes the basic attributes that you can specify on options. .. code-block:: c++ - cl::opt<**bool**> Quiet("quiet"); + cl::opt Quiet("quiet"); .. _cl::desc(...): * The **cl::desc** attribute specifies a description for the option to be - shown in the ``-help`` output for the program. + shown in the ``-help`` output for the program. This attribute supports + multi-line descriptions with lines separated by '\n'. .. _cl::value_desc: diff --git a/docs/CompilerWriterInfo.rst b/docs/CompilerWriterInfo.rst index e9a7bc876aebd..7b02a7876a7a6 100644 --- a/docs/CompilerWriterInfo.rst +++ b/docs/CompilerWriterInfo.rst @@ -20,6 +20,8 @@ ARM * `ABI `_ +* `ABI Addenda and Errata `_ + * `ARM C Language Extensions `_ AArch64 @@ -37,7 +39,7 @@ Itanium (ia64) MIPS ---- -* `MIPS Processor Architecture `_ +* `MIPS Processor Architecture `_ PowerPC ------- @@ -64,12 +66,28 @@ Other documents, collections, notes * `PowerPC64 alignment of long doubles (from GCC) `_ * `Long branch stubs for powerpc64-linux (from binutils) `_ +R600 +---- + +* `AMD R6xx shader ISA `_ +* `AMD R7xx shader ISA `_ +* `AMD Evergreen shader ISA `_ +* `AMD Cayman/Trinity shader ISA `_ +* `AMD Southern Islands Series ISA `_ +* `AMD GPU Programming Guide `_ +* `AMD Compute Resources `_ + SPARC ----- * `SPARC resources `_ * `SPARC standards `_ +SystemZ +------- + +* `z/Architecture Principles of Operation (registration required, free sign-up) `_ + X86 --- @@ -98,12 +116,17 @@ Other relevant lists ABI === +* `System V Application Binary Interface `_ +* `Itanium C++ ABI `_ + Linux ----- * `PowerPC 64-bit ELF ABI Supplement `_ * `Procedure Call Standard for the AArch64 Architecture `_ +* `ELF for the ARM Architecture `_ * `ELF for the ARM 64-bit Architecture (AArch64) `_ +* `System z ELF ABI Supplement `_ OS X ---- @@ -111,6 +134,11 @@ OS X * `Mach-O Runtime Architecture `_ * `Notes on Mach-O ABI `_ +Windows +------- + +* `Microsoft PE/COFF Specification `_ + NVPTX ===== diff --git a/docs/DeveloperPolicy.rst b/docs/DeveloperPolicy.rst index 0655559cee10e..ea5a7d1b66bab 100644 --- a/docs/DeveloperPolicy.rst +++ b/docs/DeveloperPolicy.rst @@ -68,6 +68,9 @@ 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. +Please be aware that all public LLVM mailing lists are public and archived, and +that notices of confidentiality or non-disclosure cannot be respected. + .. _patch: .. _one-off patches: @@ -107,6 +110,10 @@ rather than ``Content-Disposition: attachment``. Apple Mail gamely displays such a file inline, making it difficult to work with for reviewers using that program. +When submitting patches, please do not add confidentiality or non-disclosure +notices to the patches themselves. These notices conflict with the `LLVM +License`_ and may result in your contribution being excluded. + .. _code review: Code Reviews @@ -128,7 +135,24 @@ software. We generally follow these policies: all necessary review-related changes. #. Code review can be an iterative process, which continues until the patch is - ready to be committed. + ready to be committed. Specifically, once a patch is sent out for review, it + needs an explicit "looks good" before it is submitted. Do not assume silent + approval, or request active objections to the patch with a deadline. + +Sometimes code reviews will take longer than you would hope for, especially for +larger features. Accepted ways to speed up review times for your patches are: + +* Review other people's patches. If you help out, everybody will be more + willing to do the same for you; goodwill is our currency. +* Ping the patch. If it is urgent, provide reasons why it is important to you to + get this patch landed and ping it every couple of days. If it is + not urgent, the common courtesy ping rate is one week. Remember that you're + asking for valuable time from other professional developers. +* Ask for help on IRC. Developers on IRC will be able to either help you + directly, or tell you who might be a good reviewer. +* Split your patch into multiple smaller patches that build on each other. The + smaller your patch, the higher the probability that somebody will take a quick + look at it. Developers should participate in code reviews as both reviewers and reviewees. If someone is kind enough to review your code, you should return the diff --git a/docs/ExtendingLLVM.rst b/docs/ExtendingLLVM.rst index 3ae676a1b6e70..60cbf011e5731 100644 --- a/docs/ExtendingLLVM.rst +++ b/docs/ExtendingLLVM.rst @@ -281,12 +281,12 @@ Adding a derived type add ability to parse in the type from text assembly -#. ``llvm/lib/BitCode/Writer/Writer.cpp``: +#. ``llvm/lib/Bitcode/Writer/Writer.cpp``: modify ``void BitcodeWriter::outputType(const Type *T)`` to serialize your type -#. ``llvm/lib/BitCode/Reader/Reader.cpp``: +#. ``llvm/lib/Bitcode/Reader/Reader.cpp``: modify ``const Type *BitcodeReader::ParseType()`` to read your data type diff --git a/docs/Extensions.rst b/docs/Extensions.rst index 062804a9fc740..e308dbcdfc43c 100644 --- a/docs/Extensions.rst +++ b/docs/Extensions.rst @@ -4,7 +4,6 @@ LLVM Extensions .. contents:: :local: - :depth: 1 .. toctree:: :hidden: @@ -15,12 +14,29 @@ Introduction This document describes extensions to tools and formats LLVM seeks compatibility with. +General Assembly Syntax +=========================== + +C99-style Hexadecimal Floating-point Constants +---------------------------------------------- + +LLVM's assemblers allow floating-point constants to be written in C99's +hexadecimal format instead of decimal if desired. + +.. code-block:: gas + + .section .data + .float 0x1c2.2ap3 + Machine-specific Assembly Syntax ================================ X86/COFF-Dependent ------------------ +Relocations +^^^^^^^^^^^ + The following additional relocation type is supported: **@IMGREL** (AT&T syntax only) generates an image-relative relocation that @@ -37,3 +53,93 @@ corresponds to the COFF relocation types ``IMAGE_REL_I386_DIR32NB`` (32-bit) or .long fun@IMGREL .long (fun@imgrel + 0x3F) .long $unwind$fun@imgrel + + +``.linkonce`` Directive +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: + + ``.linkonce [ comdat type [ section identifier ] ]`` + +Supported COMDAT types: + +``discard`` + Discards duplicate sections with the same COMDAT symbol. This is the default + if no type is specified. + +``one_only`` + If the symbol is defined multiple times, the linker issues an error. + +``same_size`` + Duplicates are discarded, but the linker issues an error if any have + different sizes. + +``same_contents`` + Duplicates are discarded, but the linker issues an error if any duplicates + do not have exactly the same content. + +``associative`` + Links the section if a certain other COMDAT section is linked. This other + section is indicated by its section identifier following the comdat type. + The following restrictions apply to the associated section: + + 1. It must be the name of a section already defined. + 2. It must differ from the current section. + 3. It must be a COMDAT section. + 4. It cannot be another associative COMDAT section. + +``largest`` + Links the largest section from among the duplicates. + +``newest`` + Links the newest section from among the duplicates. + + +.. code-block:: gas + + .section .text$foo + .linkonce + ... + + .section .xdata$foo + .linkonce associative .text$foo + ... + +``.section`` Directive +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MC supports passing the information in ``.linkonce`` at the end of +``.section``. For example, these two codes are equivalent + +.. code-block:: gas + + .section secName, "dr", discard, "Symbol1" + .globl Symbol1 + Symbol1: + .long 1 + +.. code-block:: gas + + .section secName, "dr" + .linkonce discard + .globl Symbol1 + Symbol1: + .long 1 + +Note that in the combined form the COMDAT symbol is explict. This +extension exits to support multiple sections with the same name in +different comdats: + + +.. code-block:: gas + + .section secName, "dr", discard, "Symbol1" + .globl Symbol1 + Symbol1: + .long 1 + + .section secName, "dr", discard, "Symbol2" + .globl Symbol2 + Symbol2: + .long 1 diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst index 5c3a1af23cd3d..73bc5eeb1ffef 100644 --- a/docs/GarbageCollection.rst +++ b/docs/GarbageCollection.rst @@ -523,7 +523,7 @@ extension): $ cat sample.ll define void @f() gc "mygc" { entry: - ret void + ret void } $ llvm-as < sample.ll | llc -load=MyGC.so @@ -764,8 +764,8 @@ The following can be used as a template: .. code-block:: c++ - #include "llvm/Module.h" - #include "llvm/IntrinsicInst.h" + #include "llvm/IR/Module.h" + #include "llvm/IR/IntrinsicInst.h" bool MyGC::initializeCustomLowering(Module &M) { return false; @@ -896,109 +896,96 @@ in the JIT, nor using the object writers. namespace { class LLVM_LIBRARY_VISIBILITY MyGCPrinter : public GCMetadataPrinter { public: - virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + virtual void beginAssembly(AsmPrinter &AP); - virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + virtual void finishAssembly(AsmPrinter &AP); }; GCMetadataPrinterRegistry::Add 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: +The collector should use ``AsmPrinter`` to print portable assembly code. 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: .. code-block:: c++ #include "llvm/CodeGen/AsmPrinter.h" - #include "llvm/Function.h" - #include "llvm/Target/TargetMachine.h" - #include "llvm/DataLayout.h" + #include "llvm/IR/Function.h" + #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetAsmInfo.h" + #include "llvm/Target/TargetMachine.h" - void MyGCPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) { + void MyGCPrinter::beginAssembly(AsmPrinter &AP) { // 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.getDataLayout()->getPointerSize() == sizeof(int32_t)) { - AddressDirective = TAI.getData32bitsDirective(); - AddressAlignLog = 2; - } else { - AddressDirective = TAI.getData64bitsDirective(); - AddressAlignLog = 3; - } + void MyGCPrinter::finishAssembly(AsmPrinter &AP) { + MCStreamer &OS = AP.OutStreamer; + unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); // Put this in the data section. - AP.SwitchToDataSection(TAI.getDataSection()); + OS.SwitchSection(AP.getObjFileLowering().getDataSection()); // For each function... for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { GCFunctionInfo &MD = **FI; - // Emit this data structure: + // A compact GC layout. Emit this data structure: // // struct { // int32_t PointCount; - // struct { - // void *SafePointAddress; - // int32_t LiveCount; - // int32_t LiveOffsets[LiveCount]; - // } Points[PointCount]; + // void *SafePointAddress[PointCount]; + // int32_t StackFrameSize; // in words + // int32_t StackArity; + // int32_t LiveCount; + // int32_t LiveOffsets[LiveCount]; // } __gcmap_; // 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"; + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); // Emit PointCount. + OS.AddComment("safe point count"); 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); - + PE = MD.end(); PI != PE; ++PI) { // 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"); - } + OS.AddComment("safe point address"); + MCSymbol *Label = PI->Label; + AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/); + } + + // Stack information never change in safe points! Only print info from the + // first call-site. + GCFunctionInfo::iterator PI = MD.begin(); + + // Emit the stack frame size. + OS.AddComment("stack frame size (in words)"); + AP.EmitInt32(MD.getFrameSize() / IntPtrSize); + + // Emit stack arity, i.e. the number of stacked arguments. + unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6; + unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ? + MD.getFunction().arg_size() - RegisteredArgs : 0; + OS.AddComment("stack arity"); + AP.EmitInt32(StackArity); + + // Emit the number of live roots in the function. + OS.AddComment("live root count"); + AP.EmitInt32(MD.live_size(PI)); + + // And for each live root... + for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), + LE = MD.live_end(PI); + LI != LE; ++LI) { + // Emit live root's offset within the stack frame. + OS.AddComment("stack index (offset / wordsize)"); + AP.EmitInt32(LI->StackOffset); } } } @@ -1026,4 +1013,3 @@ programming. [Henderson2002] `Accurate Garbage Collection in an Uncooperative Environment `__ - diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index 6016b53bfca62..2a6b6379dce16 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -81,7 +81,7 @@ Here's the short story for getting up and running quickly with LLVM: * ``make [-j]`` --- The ``-j`` specifies the number of jobs (commands) to run simultaneously. This builds both LLVM and Clang for Debug+Asserts mode. - The ``--enabled-optimized`` configure option is used to specify a Release + The ``--enable-optimized`` configure option is used to specify a Release build. * ``make check-all`` --- This run the regression tests to ensure everything @@ -217,9 +217,7 @@ uses the package and provides other details. +--------------------------------------------------------------+-----------------+---------------------------------------------+ | `SVN `_ | >=1.3 | Subversion access to LLVM\ :sup:`2` | +--------------------------------------------------------------+-----------------+---------------------------------------------+ -| `python `_ | >=2.4 | Automated test suite\ :sup:`3` | -+--------------------------------------------------------------+-----------------+---------------------------------------------+ -| `perl `_ | >=5.6.0 | Utilities | +| `python `_ | >=2.5 | Automated test suite\ :sup:`3` | +--------------------------------------------------------------+-----------------+---------------------------------------------+ | `GNU M4 `_ | 1.4 | Macro processor for configuration\ :sup:`4` | +--------------------------------------------------------------+-----------------+---------------------------------------------+ @@ -459,15 +457,6 @@ The files are as follows, with *x.y* marking the version number: 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. - .. _checkout: Checkout LLVM from Subversion @@ -490,6 +479,8 @@ 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 3.3: **RELEASE_33/final** +* Release 3.2: **RELEASE_32/final** * Release 3.1: **RELEASE_31/final** * Release 3.0: **RELEASE_30/final** * Release 2.9: **RELEASE_29/final** @@ -758,7 +749,7 @@ The following options can be used to set or enable LLVM specific options: target names that you want available in llc. The target names use all lower case. The current set of targets is: - ``arm, cpp, hexagon, mblaze, mips, mipsel, msp430, powerpc, ptx, sparc, spu, + ``arm, cpp, hexagon, mips, mipsel, msp430, powerpc, ptx, sparc, spu, systemz, x86, x86_64, xcore``. ``--enable-doxygen`` @@ -939,6 +930,10 @@ 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). +Check :doc:`HowToCrossCompileLLVM` and `Clang docs on how to cross-compile in general +`_ for more information +about cross-compiling. + The Location of LLVM Object Files --------------------------------- @@ -1074,7 +1069,7 @@ different `tools`_. This directory holds the source code for the LLVM assembly language parser library. -``llvm/lib/BitCode/`` +``llvm/lib/Bitcode/`` This directory holds code for reading and write LLVM bitcode. @@ -1312,7 +1307,7 @@ Example with clang Clang works just like GCC by default. The standard -S and -c arguments work as usual (producing a native .s or .o file, respectively). -#. Next, compile the C file into a LLVM bitcode file: +#. Next, compile the C file into an LLVM bitcode file: .. code-block:: console diff --git a/docs/GettingStartedVS.rst b/docs/GettingStartedVS.rst index a80a9e26579a2..c46dc831eb9a9 100644 --- a/docs/GettingStartedVS.rst +++ b/docs/GettingStartedVS.rst @@ -45,13 +45,13 @@ and software you will need. Hardware -------- -Any system that can adequately run Visual Studio 2008 is fine. The LLVM +Any system that can adequately run Visual Studio 2010 is fine. The LLVM source tree and object files, libraries and executables will consume approximately 3GB. Software -------- -You will need Visual Studio 2008 or higher. Earlier versions of Visual +You will need Visual Studio 2010 or higher. Earlier versions of Visual Studio have bugs, are not completely compatible, or do not support the C++ standard well enough. @@ -164,7 +164,7 @@ An Example Using the LLVM Tool Chain return 0; } -2. Next, compile the C file into a LLVM bitcode file: +2. Next, compile the C file into an LLVM bitcode file: .. code-block:: bat diff --git a/docs/GoldPlugin.rst b/docs/GoldPlugin.rst index 17bbeb8ba9f85..28b202adf0848 100644 --- a/docs/GoldPlugin.rst +++ b/docs/GoldPlugin.rst @@ -30,29 +30,22 @@ 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: +* Download, configure and build gold with plugin support: .. code-block:: bash - $ 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 + $ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils $ mkdir build $ cd build - $ ../src/configure --enable-gold --enable-plugins + $ ../binutils/configure --enable-gold --enable-plugins --disable-werror $ 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. + That should leave you with ``build/gold/ld-new`` which supports + the ``-plugin`` option. Running ``make`` will additionally build + ``build/binutils/ar`` and ``nm-new`` binaries supporting plugins. * Build the LLVMgold plugin: Configure LLVM with - ``--with-binutils-include=/path/to/binutils/src/include`` and run + ``--with-binutils-include=/path/to/binutils/include`` and run ``make``. Usage @@ -66,17 +59,16 @@ look for the line where it runs ``collect2``. Replace that with ready to switch to using gold, backup your existing ``/usr/bin/ld`` then replace it with ``ld-new``. -You can produce bitcode files from ``clang`` using ``-emit-llvm`` or -``-flto``, or the ``-O4`` flag which is synonymous with ``-O3 -flto``. - -Any of these flags will also cause ``clang`` to look for the gold plugin in +You should produce bitcode files from ``clang`` with the option +``-flto``. This flag will also cause ``clang`` to look for the gold plugin in the ``lib`` directory under its prefix and pass 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``. +``ar`` and ``nm`` also accept the ``-plugin`` option and it's possible to +to install ``LLVMgold.so`` to ``/usr/lib/bfd-plugins`` for a seamless setup. +If you built your own gold, be sure to install the ``ar`` and ``nm-new`` you +built to ``/usr/bin``. Example of link time optimization @@ -153,7 +145,6 @@ everything is in place for an easy to use LTO build of autotooled projects: 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: @@ -163,7 +154,6 @@ everything is in place for an easy to use LTO build of autotooled projects: export CC="clang -flto" export CXX="clang++ -flto" export RANLIB=/bin/true - export CFLAGS="-O4" * Configure and build the project as usual: .. code-block:: bash diff --git a/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt b/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt index a7457846395b5..521526fbff8ee 100644 --- a/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt +++ b/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt @@ -132,6 +132,6 @@ 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.) +(i.e., return from an llvm_first_trigger() or countPath() call.) diff --git a/docs/HowToBuildOnARM.rst b/docs/HowToBuildOnARM.rst index 32ae39ba68836..f2edaef76cd10 100644 --- a/docs/HowToBuildOnARM.rst +++ b/docs/HowToBuildOnARM.rst @@ -6,7 +6,11 @@ Introduction ============ This document contains information about building/testing LLVM and -Clang on ARM. +Clang on an ARM machine. + +This document is *NOT* tailored to help you cross-compile LLVM/Clang +to ARM on another architecture, for example an x86_64 machine. To find +out more about cross-compiling, please check :doc:`HowToCrossCompileLLVM`. Notes On Building LLVM/Clang on ARM ===================================== @@ -17,19 +21,19 @@ on the ARMv6 and ARMv7 architectures and may be inapplicable to older chips. #. If you are building LLVM/Clang on an ARM board with 1G of memory or less, please use ``gold`` rather then GNU ``ld``. Building LLVM/Clang with ``--enable-optimized`` - is prefered since it consumes less memory. Otherwise, the building + is preferred since it consumes less memory. Otherwise, the building process will very likely fail due to insufficient memory. In any case it is probably a good idea to set up a swap partition. -#. If you want to run ``make - check-all`` after building LLVM/Clang, to avoid false alarms (eg, ARCMT - failure) please use at least the following configuration: +#. If you want to run ``make check-all`` after building LLVM/Clang, to avoid + false alarms (e.g., ARCMT failure) please use at least the following + configuration: .. code-block:: bash $ ../$LLVM_SRC_DIR/configure --with-abi=aapcs-vfp -#. The most popular linaro/ubuntu OS's for ARM boards, eg, the +#. The most popular Linaro/Ubuntu OS's for ARM boards, e.g., the Pandaboard, have become hard-float platforms. The following set of configuration options appears to be a good choice for this platform: @@ -41,3 +45,25 @@ on the ARMv6 and ARMv7 architectures and may be inapplicable to older chips. --target=armv7l-unknown-linux-gnueabihf --with-cpu=cortex-a9 \ --with-float=hard --with-abi=aapcs-vfp --with-fpu=neon \ --enable-targets=arm --enable-optimized --enable-assertions + +#. ARM development boards can be unstable and you may experience that cores + are disappearing, caches being flushed on every big.LITTLE switch, and + other similar issues. To help ease the effect of this, set the Linux + scheduler to "performance" on **all** cores using this little script: + + .. code-block:: bash + + # The code below requires the package 'cpufrequtils' to be installed. + for ((cpu=0; cpu<`grep -c proc /proc/cpuinfo`; cpu++)); do + sudo cpufreq-set -c $cpu -g performance + done + +#. Running the build on SD cards is ok, but they are more prone to failures + than good quality USB sticks, and those are more prone to failures than + external hard-drives (those are also a lot faster). So, at least, you + should consider to buy a fast USB stick. On systems with a fast eMMC, + that's a good option too. + +#. Make sure you have a decent power supply (dozens of dollars worth) that can + provide *at least* 4 amperes, this is especially important if you use USB + devices with your board. diff --git a/docs/HowToCrossCompileLLVM.rst b/docs/HowToCrossCompileLLVM.rst new file mode 100644 index 0000000000000..1072517e4c2b6 --- /dev/null +++ b/docs/HowToCrossCompileLLVM.rst @@ -0,0 +1,175 @@ +=================================================================== +How To Cross-Compile Clang/LLVM using Clang/LLVM +=================================================================== + +Introduction +============ + +This document contains information about building LLVM and +Clang on host machine, targeting another platform. + +For more information on how to use Clang as a cross-compiler, +please check http://clang.llvm.org/docs/CrossCompilation.html. + +TODO: Add MIPS and other platforms to this document. + +Cross-Compiling from x86_64 to ARM +================================== + +In this use case, we'll be using CMake and Ninja, on a Debian-based Linux +system, cross-compiling from an x86_64 host (most Intel and AMD chips +nowadays) to a hard-float ARM target (most ARM targets nowadays). + +The packages you'll need are: + + * ``cmake`` + * ``ninja-build`` (from backports in Ubuntu) + * ``gcc-4.7-arm-linux-gnueabihf`` + * ``gcc-4.7-multilib-arm-linux-gnueabihf`` + * ``binutils-arm-linux-gnueabihf`` + * ``libgcc1-armhf-cross`` + * ``libsfgcc1-armhf-cross`` + * ``libstdc++6-armhf-cross`` + * ``libstdc++6-4.7-dev-armhf-cross`` + +Configuring CMake +----------------- + +For more information on how to configure CMake for LLVM/Clang, +see :doc:`CMake`. + +The CMake options you need to add are: + * ``-DCMAKE_CROSSCOMPILING=True`` + * ``-DCMAKE_INSTALL_PREFIX=`` + * ``-DLLVM_TABLEGEN=/llvm-tblgen`` + * ``-DCLANG_TABLEGEN=/clang-tblgen`` + * ``-DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf`` + * ``-DLLVM_TARGET_ARCH=ARM`` + * ``-DLLVM_TARGETS_TO_BUILD=ARM`` + * ``-DCMAKE_CXX_FLAGS='-target armv7a-linux-gnueabihf -mcpu=cortex-a9 -I/usr/arm-linux-gnueabihf/include/c++/4.7.2/arm-linux-gnueabihf/ -I/usr/arm-linux-gnueabihf/include/ -mfloat-abi=hard -ccc-gcc-name arm-linux-gnueabihf-gcc'`` + +The TableGen options are required to compile it with the host compiler, +so you'll need to compile LLVM (or at least ``llvm-tblgen``) to your host +platform before you start. The CXX flags define the target, cpu (which +defaults to ``fpu=VFP3`` with NEON), and forcing the hard-float ABI. If you're +using Clang as a cross-compiler, you will *also* have to set ``-ccc-gcc-name``, +to make sure it picks the correct linker. + +Most of the time, what you want is to have a native compiler to the +platform itself, but not others. It might not even be feasible to +produce x86 binaries from ARM targets, so there's no point in compiling +all back-ends. For that reason, you should also set the +``TARGETS_TO_BUILD`` to only build the ARM back-end. + +You must set the ``CMAKE_INSTALL_PREFIX``, otherwise a ``ninja install`` +will copy ARM binaries to your root filesystem, which is not what you +want. + +Hacks +----- + +There are some bugs in current LLVM, which require some fiddling before +running CMake: + +#. If you're using Clang as the cross-compiler, there is a problem in + the LLVM ARM back-end that is producing absolute relocations on + position-independent code (``R_ARM_THM_MOVW_ABS_NC``), so for now, you + should disable PIC: + + .. code-block:: bash + + -DLLVM_ENABLE_PIC=False + + This is not a problem, since Clang/LLVM libraries are statically + linked anyway, it shouldn't affect much. + +#. The ARM libraries won't be installed in your system, and possibly + not easily installable anyway, so you'll have to build/download + them separately. But the CMake prepare step, which checks for + dependencies, will check the *host* libraries, not the *target* + ones. + + A quick way of getting the libraries is to download them from + a distribution repository, like Debian (http://packages.debian.org/wheezy/), + and download the missing libraries. Note that the ``libXXX`` + will have the shared objects (``.so``) and the ``libXXX-dev`` will + give you the headers and the static (``.a``) library. Just in + case, download both. + + The ones you need for ARM are: ``libtinfo``, ``zlib1g``, + ``libxml2`` and ``liblzma``. In the Debian repository you'll + find downloads for all architectures. + + After you download and unpack all ``.deb`` packages, copy all + ``.so`` and ``.a`` to a directory, make the appropriate + symbolic links (if necessary), and add the relevant ``-L`` + and ``-I`` paths to ``-DCMAKE_CXX_FLAGS`` above. + + +Running CMake and Building +-------------------------- + +Finally, if you're using your platform compiler, run: + + .. code-block:: bash + + $ cmake -G Ninja + +If you're using Clang as the cross-compiler, run: + + .. code-block:: bash + + $ CC='clang' CXX='clang++' cmake -G Ninja + +If you have ``clang``/``clang++`` on the path, it should just work, and special +Ninja files will be created in the build directory. I strongly suggest +you to run ``cmake`` on a separate build directory, *not* inside the +source tree. + +To build, simply type: + + .. code-block:: bash + + $ ninja + +It should automatically find out how many cores you have, what are +the rules that needs building and will build the whole thing. + +You can't run ``ninja check-all`` on this tree because the created +binaries are targeted to ARM, not x86_64. + +Installing and Using +-------------------- + +After the LLVM/Clang has built successfully, you should install it +via: + + .. code-block:: bash + + $ ninja install + +which will create a sysroot on the install-dir. You can then tar +that directory into a binary with the full triple name (for easy +identification), like: + + .. code-block:: bash + + $ ln -sf arm-linux-gnueabihf-clang + $ tar zchf arm-linux-gnueabihf-clang.tar.gz arm-linux-gnueabihf-clang + +If you copy that tarball to your target board, you'll be able to use +it for running the test-suite, for example. Follow the guidelines at +http://llvm.org/docs/lnt/quickstart.html, unpack the tarball in the +test directory, and use options: + + .. code-block:: bash + + $ ./sandbox/bin/python sandbox/bin/lnt runtest nt \ + --sandbox sandbox \ + --test-suite `pwd`/test-suite \ + --cc `pwd`/arm-linux-gnueabihf-clang/bin/clang \ + --cxx `pwd`/arm-linux-gnueabihf-clang/bin/clang++ + +Remember to add the ``-jN`` options to ``lnt`` to the number of CPUs +on your board. Also, the path to your clang has to be absolute, so +you'll need the `pwd` trick above. diff --git a/docs/HowToReleaseLLVM.rst b/docs/HowToReleaseLLVM.rst index 31877bd35ac89..bc3b093d755e4 100644 --- a/docs/HowToReleaseLLVM.rst +++ b/docs/HowToReleaseLLVM.rst @@ -14,6 +14,9 @@ including subprojects: e.g., ``clang`` and ``dragonegg`` --- to the public. It is the Release Manager's responsibility to ensure that a high quality build of LLVM is released. +If you're looking for the document on how to test the release candidates and +create the binary packages, please refer to the :doc:`ReleaseProcess` instead. + .. _timeline: Release Timeline diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 7743ff06a0d76..810455cbc3a7f 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -127,7 +127,10 @@ lexical features of LLVM: #. Comments are delimited with a '``;``' and go until the end of line. #. Unnamed temporaries are created when the result of a computation is not assigned to a named value. -#. Unnamed temporaries are numbered sequentially +#. Unnamed temporaries are numbered sequentially (using a per-function + incrementing counter, starting with 0). Note that basic blocks are + included in this numbering. For example, if the entry basic block is not + given a label name, then it will get number 0. It also shows a convention that we follow in this document. When demonstrating instructions, we will follow an instruction with a comment @@ -266,13 +269,6 @@ linkage: ``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. -``linkonce_odr_auto_hide`` - Similar to "``linkonce_odr``", but nothing in the translation unit - takes the address of this definition. For instance, functions that - had an inline definition, but the compiler decided not to inline it. - ``linkonce_odr_auto_hide`` may have only ``default`` visibility. The - symbols are removed by the linker from the final linked image - (executable or dynamic library). ``external`` If none of the above identifiers are used, the global is externally visible, meaning that it participates in linkage and can be used to @@ -304,9 +300,6 @@ declarations), they are accessible outside of the current module. It is illegal for a function *declaration* to have any linkage type other than ``external``, ``dllimport`` or ``extern_weak``. -Aliases can have only ``external``, ``internal``, ``weak`` or -``weak_odr`` linkages. - .. _callingconv: Calling Conventions @@ -386,6 +379,8 @@ More calling conventions can be added/defined on an as-needed basis, to support Pascal conventions or any other well-known target-independent convention. +.. _visibilitystyles: + Visibility Styles ----------------- @@ -411,6 +406,8 @@ styles: defining module will bind to the local symbol. That is, the symbol cannot be overridden by another module. +.. _namedtypes: + Named Types ----------- @@ -443,9 +440,13 @@ Global Variables ---------------- 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. +instead of run-time. + +Global variables definitions must be initialized, may have an explicit section +to be placed in, and may have an optional explicit alignment specified. + +Global variables in other translation units can also be declared, in which +case they don't have an initializer. 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 @@ -527,6 +528,12 @@ with an initializer, section, and alignment: @G = addrspace(5) constant float 1.0, section "foo", align 4 +The following example just declares a global variable + +.. code-block:: llvm + + @G = external global i32 + The following example defines a thread-local global with the ``initialexec`` TLS model: @@ -547,23 +554,26 @@ an optional ``unnamed_addr`` attribute, a return type, an optional name, a (possibly empty) argument list (each with optional :ref:`parameter attributes `), optional :ref:`function attributes `, an optional section, an optional alignment, an optional :ref:`garbage -collector name `, an opening curly brace, a list of basic blocks, -and a closing curly brace. +collector name `, an optional :ref:`prefix `, an opening +curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an optional :ref:`linkage type `, an optional :ref:`visibility style `, an optional :ref:`calling convention `, an optional ``unnamed_addr`` attribute, a return type, an optional :ref:`parameter attribute ` for the return type, a function -name, a possibly empty list of arguments, an optional alignment, and an -optional :ref:`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 -:ref:`terminator ` instruction (such as a branch or function -return). +name, a possibly empty list of arguments, an optional alignment, an optional +:ref:`garbage collector name ` and an optional :ref:`prefix `. + +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 :ref:`terminator ` instruction (such as a branch or +function return). If an explicit label is not provided, a block is assigned an +implicit numbered label, using the next value from the same counter as used for +unnamed temporaries (:ref:`see above`). For example, if a function +entry block does not have an explicit label, it will be assigned label "%0", +then the first unnamed temporary in that block will be "%1", etc. 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 @@ -589,7 +599,9 @@ Syntax:: [cconv] [ret attrs] @ ([argument list]) [fn Attrs] [section "name"] [align N] - [gc] { ... } + [gc] [prefix Constant] { ... } + +.. _langref_aliases: Aliases ------- @@ -603,6 +615,12 @@ Syntax:: @ = alias [Linkage] [Visibility] @ +The linkage must be one of ``private``, ``linker_private``, +``linker_private_weak``, ``internal``, ``linkonce``, ``weak``, +``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers +might not correctly handle dropping a weak symbol that is aliased by a non weak +alias. + .. _namedmetadatastructure: Named Metadata @@ -692,7 +710,7 @@ Currently, only the following parameter attributes are defined: the first parameter. This is not a valid attribute for return values. ``noalias`` - This indicates that pointer values `*based* ` on + This indicates that pointer values :ref:`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 @@ -722,14 +740,13 @@ Currently, only the following parameter attributes are defined: attribute for return values and can only be applied to one parameter. ``returned`` - This indicates that the value of the function always returns the value - of the parameter as its return value. This is an optimization hint to - the code generator when generating the caller, allowing tail call - optimization and omission of register saves and restores in some cases; - it is not checked or enforced when generating the callee. The parameter - and the function return type must be valid operands for the - :ref:`bitcast instruction `. This is not a valid attribute for - return values and can only be applied to one parameter. + This indicates that the function always returns the argument as its return + value. This is an optimization hint to the code generator when generating + the caller, allowing tail call optimization and omission of register saves + and restores in some cases; it is not checked or enforced when generating + the callee. The parameter and the function return type must be valid + operands for the :ref:`bitcast instruction `. This is not a + valid attribute for return values and can only be applied to one parameter. .. _gc: @@ -747,6 +764,55 @@ 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. +.. _prefixdata: + +Prefix Data +----------- + +Prefix data is data associated with a function which the code generator +will emit immediately before the function body. The purpose of this feature +is to allow frontends to associate language-specific runtime metadata with +specific functions and make it available through the function pointer while +still allowing the function pointer to be called. To access the data for a +given function, a program may bitcast the function pointer to a pointer to +the constant's type. This implies that the IR symbol points to the start +of the prefix data. + +To maintain the semantics of ordinary function calls, the prefix data must +have a particular format. Specifically, it must begin with a sequence of +bytes which decode to a sequence of machine instructions, valid for the +module's target, which transfer control to the point immediately succeeding +the prefix data, without performing any other visible action. This allows +the inliner and other passes to reason about the semantics of the function +definition without needing to reason about the prefix data. Obviously this +makes the format of the prefix data highly target dependent. + +Prefix data is laid out as if it were an initializer for a global variable +of the prefix data's type. No padding is automatically placed between the +prefix data and the function body. If padding is required, it must be part +of the prefix data. + +A trivial example of valid prefix data for the x86 architecture is ``i8 144``, +which encodes the ``nop`` instruction: + +.. code-block:: llvm + + define void @f() prefix i8 144 { ... } + +Generally prefix data can be formed by encoding a relative branch instruction +which skips the metadata, as in this example of valid prefix data for the +x86_64 architecture, where the first two bytes encode ``jmp .+10``: + +.. code-block:: llvm + + %0 = type <{ i8, i8, i8* }> + + define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... } + +A function may have prefix data but no body. This has similar semantics +to the ``available_externally`` linkage in that the data may be used by the +optimizers but will not be emitted in the object file. + .. _attrgrp: Attribute Groups @@ -807,24 +873,36 @@ example: 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. -``nonlazybind`` - This attribute suppresses lazy symbol binding for the function. This - may make calls to the function faster, at the cost of extra program - startup time if the function is not called during program startup. +``builtin`` + This indicates that the callee function at a call site should be + recognized as a built-in function, even though the function's declaration + uses the ``nobuiltin`` attribute. This is only valid at call sites for + direct calls to functions which are declared with the ``nobuiltin`` + attribute. +``cold`` + This attribute indicates that this function is rarely called. When + computing edge weights, basic blocks post-dominated by a cold + function call are also considered to be cold; and, thus, given low + weight. ``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. +``minsize`` + This attribute suggests that optimization passes and code generator + passes make choices that keep the code size of this function as small + as possible and perform optimizations that may sacrifice runtime + performance in order to minimize the size of the generated code. ``naked`` This attribute disables prologue / epilogue emission for the function. This can have very system-specific consequences. ``nobuiltin`` - This indicates that the callee function at a call site is not - recognized as a built-in function. LLVM will retain the original call - and not replace it with equivalent code based on the semantics of the - built-in function. This is only valid at call sites, not on function - declarations or definitions. + This indicates that the callee function at a call site is not recognized as + a built-in function. LLVM will retain the original call and not replace it + with equivalent code based on the semantics of the built-in function, unless + the call site uses the ``builtin`` attribute. This is valid at call sites + and on function declarations and definitions. ``noduplicate`` This attribute indicates that calls to the function cannot be duplicated. A call to a ``noduplicate`` function may be moved @@ -842,6 +920,10 @@ example: 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. +``nonlazybind`` + This attribute suppresses lazy symbol binding for the function. This + may make calls to the function faster, at the cost of extra program + startup time if the function is not called during program startup. ``noredzone`` This attribute indicates that the code generator should not use a red zone, even if the target-specific ABI normally permits it. @@ -853,22 +935,39 @@ example: 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. +``optnone`` + This function attribute indicates that the function is not optimized + by any optimization or code generator passes with the + exception of interprocedural optimization passes. + This attribute cannot be used together with the ``alwaysinline`` + attribute; this attribute is also incompatible + with the ``minsize`` attribute and the ``optsize`` attribute. + + This attribute requires the ``noinline`` attribute to be specified on + the function as well, so the function is never inlined into any caller. + Only functions with the ``alwaysinline`` attribute are valid + candidates for inlining into the body of this function. ``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. + and otherwise do optimizations specifically to reduce code size as + long as they do not significantly impact runtime performance. ``readnone`` - This attribute indicates that the function computes its result (or - decides to unwind an exception) based strictly on its arguments, + On a function, 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. + + On an argument, this attribute indicates that the function does not + dereference that pointer argument, even though it may read or write the + memory that the pointer points to if accessed through other pointers. ``readonly`` - This attribute indicates that the function does not write through - any pointer arguments (including ``byval`` arguments) or otherwise + On a function, 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 @@ -876,6 +975,10 @@ example: called with the same set of arguments and global state. It cannot unwind an exception by calling the ``C++`` exception throwing methods. + + On an argument, this attribute indicates that the function does not write + through this pointer argument, even though it may write to the memory that + the pointer points to. ``returns_twice`` This attribute indicates that this function can return twice. The C ``setjmp`` is an example of such a function. The compiler disables @@ -960,6 +1063,8 @@ 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. +.. _langref_datalayout: + Data Layout ----------- @@ -1030,7 +1135,9 @@ 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 +- ``p:64:64:64`` - 64-bit pointers with 64-bit alignment. +- ``p[n]:64:64:64`` - Other address spaces are assumed to be the + same as the default address space. - ``S0`` - natural stack alignment is unspecified - ``i1:8:8`` - i1 is 8-bit (byte) aligned - ``i8:8:8`` - i8 is 8-bit (byte) aligned @@ -1076,6 +1183,30 @@ don't have to specify the string. This will disable some optimizations that require precise layout information, but this also prevents those optimizations from introducing target specificity into the IR. +.. _langref_triple: + +Target Triple +------------- + +A module may specify a target triple string that describes the target +host. The syntax for the target triple is simply: + +.. code-block:: llvm + + target triple = "x86_64-apple-macosx10.7.0" + +The *target triple* string consists of a series of identifiers delimited +by the minus sign character ('-'). The canonical forms are: + +:: + + ARCHITECTURE-VENDOR-OPERATING_SYSTEM + ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT + +This information is passed along to the backend so that it generates +code for the proper architecture. It's possible to override this on the +command line with the ``-mtriple`` command line option. + .. _pointeraliasing: Pointer Aliasing Rules @@ -1349,6 +1480,8 @@ 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. +.. _typeclassifications: + Type Classifications -------------------- @@ -1624,9 +1757,10 @@ Function Type 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. +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 void type or first class type --- except for :ref:`label ` +and :ref:`metadata ` types. Syntax: """"""" @@ -1636,11 +1770,11 @@ Syntax: () ...where '````' 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 -:ref:`variable argument handling intrinsic ` functions. -'````' is any type except :ref:`label `. +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 :ref:`variable argument +handling intrinsic ` functions. '````' is any type +except :ref:`label ` and :ref:`metadata `. Examples: """"""""" @@ -1862,6 +1996,8 @@ followed by 4 hexadecimal digits. All hexadecimal formats are big-endian There are no constants of type x86mmx. +.. _complexconstants: + Complex Constants ----------------- @@ -2183,6 +2319,8 @@ instruction. Finally, some targets may provide defined semantics when using the value as the operand to an inline assembly, but that is target specific. +.. _constantexprs: + Constant Expressions -------------------- @@ -2247,6 +2385,10 @@ The following is the syntax for constant expressions: Convert a constant, CST, to another TYPE. The constraints of the operands are the same as those for the :ref:`bitcast instruction `. +``addrspacecast (CST to TYPE)`` + Convert a constant pointer or constant vector of pointer, CST, to another + TYPE in a different address space. The constraints of the operands are the + same as those for the :ref:`addrspacecast instruction `. ``getelementptr (CSTPTR, IDX0, IDX1, ...)``, ``getelementptr inbounds (CSTPTR, IDX0, IDX1, ...)`` Perform the :ref:`getelementptr operation ` on constants. As with the :ref:`getelementptr ` @@ -2287,6 +2429,8 @@ The following is the syntax for constant expressions: Other Values ============ +.. _inlineasmexprs: + Inline Assembler Expressions ---------------------------- @@ -2544,8 +2688,8 @@ Examples: It is sometimes useful to attach information to loop constructs. Currently, loop metadata is implemented as metadata attached to the branch instruction in the loop latch block. This type of metadata refer to a metadata node that is -guaranteed to be separate for each loop. The loop-level metadata is prefixed -with ``llvm.loop``. +guaranteed to be separate for each loop. The loop identifier metadata is +specified with the name ``llvm.loop``. The loop identifier metadata is implemented using a metadata that refers to itself to avoid merging it with any other identifier metadata, e.g., @@ -2559,32 +2703,17 @@ constructs: !0 = metadata !{ metadata !0 } !1 = metadata !{ metadata !1 } +The loop identifier metadata can be used to specify additional per-loop +metadata. Any operands after the first operand can be treated as user-defined +metadata. For example the ``llvm.vectorizer.unroll`` metadata is understood +by the loop vectorizer to indicate how many times to unroll the loop: -'``llvm.loop.parallel``' Metadata -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. code-block:: llvm -This loop metadata can be used to communicate that a loop should be considered -a parallel loop. The semantics of parallel loops in this case is the one -with the strongest cross-iteration instruction ordering freedom: the -iterations in the loop can be considered completely independent of each -other (also known as embarrassingly parallel loops). - -This metadata can originate from a programming language with parallel loop -constructs. In such a case it is completely the programmer's responsibility -to ensure the instructions from the different iterations of the loop can be -executed in an arbitrary order, in parallel, or intertwined. No loop-carried -dependency checking at all must be expected from the compiler. - -In order to fulfill the LLVM requirement for metadata to be safely ignored, -it is important to ensure that a parallel loop is converted to -a sequential loop in case an optimization (agnostic of the parallel loop -semantics) converts the loop back to such. This happens when new memory -accesses that do not fulfill the requirement of free ordering across iterations -are added to the loop. Therefore, this metadata is required, but not -sufficient, to consider the loop at hand a parallel loop. For a loop -to be parallel, all its memory accessing instructions need to be -marked with the ``llvm.mem.parallel_loop_access`` metadata that refer -to the same loop identifier metadata that identify the loop at hand. + br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0 + ... + !0 = metadata !{ metadata !0, metadata !1 } + !1 = metadata !{ metadata !"llvm.vectorizer.unroll", i32 2 } '``llvm.mem``' ^^^^^^^^^^^^^^^ @@ -2596,29 +2725,28 @@ for optimizations are prefixed with ``llvm.mem``. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For a loop to be parallel, in addition to using -the ``llvm.loop.parallel`` metadata to mark the loop latch branch instruction, +the ``llvm.loop`` metadata to mark the loop latch branch instruction, also all of the memory accessing instructions in the loop body need to be marked with the ``llvm.mem.parallel_loop_access`` metadata. If there is at least one memory accessing instruction not marked with the metadata, -the loop, despite it possibly using the ``llvm.loop.parallel`` metadata, -must be considered a sequential loop. This causes parallel loops to be +the loop must be considered a sequential loop. This causes parallel loops to be converted to sequential loops due to optimization passes that are unaware of the parallel semantics and that insert new memory instructions to the loop body. Example of a loop that is considered parallel due to its correct use of -both ``llvm.loop.parallel`` and ``llvm.mem.parallel_loop_access`` +both ``llvm.loop`` and ``llvm.mem.parallel_loop_access`` metadata types that refer to the same loop identifier metadata. .. code-block:: llvm for.body: - ... - %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 - ... - store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 - ... - br i1 %exitcond, label %for.end, label %for.body, !llvm.loop.parallel !0 + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0 for.end: ... @@ -2634,27 +2762,75 @@ the loop identifier metadata node directly: ... inner.for.body: - ... - %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 - ... - store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 - ... - br i1 %exitcond, label %inner.for.end, label %inner.for.body, !llvm.loop.parallel !1 + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %inner.for.end, label %inner.for.body, !llvm.loop !1 inner.for.end: - ... - %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 - ... - store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 - ... - br i1 %exitcond, label %outer.for.end, label %outer.for.body, !llvm.loop.parallel !2 + ... + %0 = load i32* %arrayidx, align 4, !llvm.mem.parallel_loop_access !0 + ... + store i32 %0, i32* %arrayidx4, align 4, !llvm.mem.parallel_loop_access !0 + ... + br i1 %exitcond, label %outer.for.end, label %outer.for.body, !llvm.loop !2 outer.for.end: ; preds = %for.body ... - !0 = metadata !{ metadata !1, metadata !2 } ; a list of parallel loop identifiers - !1 = metadata !{ metadata !1 } ; an identifier for the inner parallel loop - !2 = metadata !{ metadata !2 } ; an identifier for the outer parallel loop + !0 = metadata !{ metadata !1, metadata !2 } ; a list of loop identifiers + !1 = metadata !{ metadata !1 } ; an identifier for the inner loop + !2 = metadata !{ metadata !2 } ; an identifier for the outer loop + +'``llvm.vectorizer``' +^^^^^^^^^^^^^^^^^^^^^ + +Metadata prefixed with ``llvm.vectorizer`` is used to control per-loop +vectorization parameters such as vectorization factor and unroll factor. + +``llvm.vectorizer`` metadata should be used in conjunction with ``llvm.loop`` +loop identification metadata. + +'``llvm.vectorizer.unroll``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This metadata instructs the loop vectorizer to unroll the specified +loop exactly ``N`` times. + +The first operand is the string ``llvm.vectorizer.unroll`` and the second +operand is an integer specifying the unroll factor. For example: + +.. code-block:: llvm + + !0 = metadata !{ metadata !"llvm.vectorizer.unroll", i32 4 } + +Note that setting ``llvm.vectorizer.unroll`` to 1 disables unrolling of the +loop. + +If ``llvm.vectorizer.unroll`` is set to 0 then the amount of unrolling will be +determined automatically. + +'``llvm.vectorizer.width``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata sets the target width of the vectorizer to ``N``. Without +this metadata, the vectorizer will choose a width automatically. +Regardless of this metadata, the vectorizer will only vectorize loops if +it believes it is valid to do so. + +The first operand is the string ``llvm.vectorizer.width`` and the second +operand is an integer specifying the width. For example: + +.. code-block:: llvm + + !0 = metadata !{ metadata !"llvm.vectorizer.width", i32 4 } + +Note that setting ``llvm.vectorizer.width`` to 1 disables vectorization of the +loop. + +If ``llvm.vectorizer.width`` is set to 0 then the width will be determined +automatically. Module Flags Metadata ===================== @@ -2856,6 +3032,8 @@ Each individual option is required to be either a valid option for the target's linker, or an option that is reserved by the target specific assembly writer or object file emitter. No other aspect of these options is defined by the IR. +.. _intrinsicglobalvariables: + Intrinsic Global Variables ========================== @@ -2865,13 +3043,16 @@ 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. +.. _gv_llvmused: + The '``llvm.used``' Global Variable ----------------------------------- -The ``@llvm.used`` global is an array which has :ref:`appending linkage -`. This array contains a list of pointers to global -variables, functions and aliases which may optionally have a pointer cast formed -of bitcast or getelementptr. For example, a legal use of it is: +The ``@llvm.used`` global is an array which has +:ref:`appending linkage `. This array contains a list of +pointers to named global variables, functions and aliases which may optionally +have a pointer cast formed of bitcast or getelementptr. For example, a legal +use of it is: .. code-block:: llvm @@ -2885,16 +3066,18 @@ of bitcast or getelementptr. For example, a legal use of it is: If a symbol 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 -symbol 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. +symbol that it cannot see (which is why they have to be named). 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. +.. _gv_llvmcompilerused: + The '``llvm.compiler.used``' Global Variable -------------------------------------------- @@ -2907,6 +3090,8 @@ by ``@llvm.used``. This is a rare construct that should only be used in rare circumstances, and should not be exposed to source languages. +.. _gv_llvmglobalctors: + The '``llvm.global_ctors``' Global Variable ------------------------------------------- @@ -2921,6 +3106,8 @@ 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. +.. _llvmglobaldtors: + The '``llvm.global_dtors``' Global Variable ------------------------------------------- @@ -4007,7 +4194,7 @@ Example: = lshr i32 4, 1 ; yields {i32}:result = 2 = lshr i32 4, 2 ; yields {i32}:result = 1 = lshr i8 4, 3 ; yields {i8}:result = 0 - = lshr i8 -2, 1 ; yields {i8}:result = 0x7FFFFFFF + = lshr i8 -2, 1 ; yields {i8}:result = 0x7F = lshr i32 1, 32 ; undefined = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2> ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1> @@ -4572,16 +4759,16 @@ 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 ```` corresponding to a metadata node with one +metadata name ```` 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 +metadata 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. The optional ``!invariant.load`` metadata must reference a single -metatadata name ```` corresponding to a metadata node with no -entries. The existence of the ``!invariant.load`` metatadata on the +metadata name ```` corresponding to a metadata node with no +entries. The existence of the ``!invariant.load`` metadata on the instruction tells the optimizer and code generator that this load address points to memory which does not change value during program execution. The optimizer may then move this load around, for example, by @@ -4657,9 +4844,9 @@ 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 +The optional ``!nontemporal`` metadata must reference a single metadata name ```` corresponding to a metadata node with one ``i32`` entry of -value 1. The existence of the ``!nontemporal`` metatadata on the instruction +value 1. The existence of the ``!nontemporal`` metadata 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 @@ -5531,24 +5718,24 @@ 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 :ref:`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). +also be a non-aggregate :ref:`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 of the same size. 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 (or vector of pointers) types may -only be converted to other pointer (or vector of pointers) types with -this instruction. To convert pointers to other types, use the -:ref:`inttoptr ` or :ref:`ptrtoint ` instructions -first. +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 (or vector of +pointers) types may only be converted to other pointer (or vector of +pointers) types with the same address space through this instruction. +To convert pointers to other types, use the :ref:`inttoptr ` +or :ref:`ptrtoint ` instructions first. Example: """""""" @@ -5560,6 +5747,51 @@ Example: %Z = bitcast <2 x int> %V to i64; ; yields i64: %V %Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*> +.. _i_addrspacecast: + +'``addrspacecast .. to``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = addrspacecast to ; yields pty2 + +Overview: +""""""""" + +The '``addrspacecast``' instruction converts ``ptrval`` from ``pty`` in +address space ``n`` to type ``pty2`` in address space ``m``. + +Arguments: +"""""""""" + +The '``addrspacecast``' instruction takes a pointer or vector of pointer value +to cast and a pointer type to cast it to, which must have a different +address space. + +Semantics: +"""""""""" + +The '``addrspacecast``' instruction converts the pointer value +``ptrval`` to type ``pty2``. It can be a *no-op cast* or a complex +value modification, depending on the target and the address space +pair. Pointer conversions within the same address space must be +performed with the ``bitcast`` instruction. Note that if the address space +conversion is legal then both result and operand refer to the same memory +location. + +Example: +"""""""" + +.. code-block:: llvm + + %X = addrspacecast i32* %x to i32 addrspace(1)* ; yields i32 addrspace(1)*:%x + %Y = addrspacecast i32 addrspace(1)* %y to i64 addrspace(2)* ; yields i64 addrspace(2)*:%y + %Z = addrspacecast <4 x i32*> %z to <4 x float addrspace(3)*> ; yields <4 x float addrspace(3)*>:%z + .. _otherops: Other Operations @@ -6209,7 +6441,7 @@ Syntax: :: - declare void %llvm.va_start(i8* ) + declare void @llvm.va_start(i8* ) Overview: """"""""" @@ -6657,6 +6889,9 @@ 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. +Note that runtime support may be conditional on the privilege-level code is +running at and the host platform. + Standard C Library Intrinsics ----------------------------- @@ -6718,7 +6953,7 @@ 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. +argument, otherwise it should be set to 0 or 1 (both meaning no alignment). '``llvm.memmove``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -6773,7 +7008,7 @@ 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. +otherwise it should be set to 0 or 1 (both meaning no alignment). '``llvm.memset.*``' Intrinsics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -6824,7 +7059,7 @@ 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. +it should be set to 0 or 1 (both meaning no alignment). '``llvm.sqrt.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7260,6 +7495,42 @@ Semantics: This function returns the same values as the libm ``fabs`` functions would, and handles error conditions in the same way. +'``llvm.copysign.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.copysign`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.copysign.f32(float %Mag, float %Sgn) + declare double @llvm.copysign.f64(double %Mag, double %Sgn) + declare x86_fp80 @llvm.copysign.f80(x86_fp80 %Mag, x86_fp80 %Sgn) + declare fp128 @llvm.copysign.f128(fp128 %Mag, fp128 %Sgn) + declare ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 %Mag, ppc_fp128 %Sgn) + +Overview: +""""""""" + +The '``llvm.copysign.*``' intrinsics return a value with the magnitude of the +first operand and the sign of the second operand. + +Arguments: +"""""""""" + +The arguments and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``copysign`` +functions would, and handles error conditions in the same way. + '``llvm.floor.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7439,6 +7710,42 @@ Semantics: This function returns the same values as the libm ``nearbyint`` functions would, and handles error conditions in the same way. +'``llvm.round.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.round`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.round.f32(float %Val) + declare double @llvm.round.f64(double %Val) + declare x86_fp80 @llvm.round.f80(x86_fp80 %Val) + declare fp128 @llvm.round.f128(fp128 %Val) + declare ppc_fp128 @llvm.round.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.round.*``' intrinsics returns the operand rounded to the +nearest integer. + +Arguments: +"""""""""" + +The argument and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +This function returns the same values as the libm ``round`` +functions would, and handles error conditions in the same way. + Bit Manipulation Intrinsics --------------------------- @@ -8512,14 +8819,52 @@ 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 +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 by ``llvm.stackprotectorcheck``. If they are +different, then ``llvm.stackprotectorcheck`` causes the program to abort by +calling the ``__stack_chk_fail()`` function. + +'``llvm.stackprotectorcheck``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.stackprotectorcheck(i8** ) + +Overview: +""""""""" + +The ``llvm.stackprotectorcheck`` intrinsic compares ``guard`` against an already +created stack protector and if they are not equal calls the ``__stack_chk_fail()`` function. +Arguments: +"""""""""" + +The ``llvm.stackprotectorcheck`` intrinsic requires one pointer argument, the +the variable ``@__stack_chk_guard``. + +Semantics: +"""""""""" + +This intrinsic is provided to perform the stack protector check by comparing +``guard`` with the stack slot created by ``llvm.stackprotector`` and if the +values do not match call the ``__stack_chk_fail()`` function. + +The reason to provide this as an IR level intrinsic instead of implementing it +via other IR operations is that in order to perform this operation at the IR +level without an intrinsic, one would need to create additional basic blocks to +handle the success/failure cases. This makes it difficult to stop the stack +protector check from disrupting sibling tail calls in Codegen. With this +intrinsic, we are able to generate the stack protector basic blocks late in +codegen after the tail call decision has occurred. + '``llvm.objectsize``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/MCJIT-creation.png b/docs/MCJIT-creation.png new file mode 100644 index 0000000000000..7abdb9df28a97 Binary files /dev/null and b/docs/MCJIT-creation.png differ diff --git a/docs/MCJIT-dyld-load.png b/docs/MCJIT-dyld-load.png new file mode 100644 index 0000000000000..1534190378cbc Binary files /dev/null and b/docs/MCJIT-dyld-load.png differ diff --git a/docs/MCJIT-engine-builder.png b/docs/MCJIT-engine-builder.png new file mode 100644 index 0000000000000..8fdd7a94aad56 Binary files /dev/null and b/docs/MCJIT-engine-builder.png differ diff --git a/docs/MCJIT-load-object.png b/docs/MCJIT-load-object.png new file mode 100644 index 0000000000000..533a52e17f7e1 Binary files /dev/null and b/docs/MCJIT-load-object.png differ diff --git a/docs/MCJIT-load.png b/docs/MCJIT-load.png new file mode 100644 index 0000000000000..9672a663403d2 Binary files /dev/null and b/docs/MCJIT-load.png differ diff --git a/docs/MCJIT-resolve-relocations.png b/docs/MCJIT-resolve-relocations.png new file mode 100644 index 0000000000000..fedeacc4a92fe Binary files /dev/null and b/docs/MCJIT-resolve-relocations.png differ diff --git a/docs/MCJITDesignAndImplementation.rst b/docs/MCJITDesignAndImplementation.rst new file mode 100644 index 0000000000000..2cb62964d465e --- /dev/null +++ b/docs/MCJITDesignAndImplementation.rst @@ -0,0 +1,180 @@ +=============================== +MCJIT Design and Implementation +=============================== + +Introduction +============ + +This document describes the internal workings of the MCJIT execution +engine and the RuntimeDyld component. It is intended as a high level +overview of the implementation, showing the flow and interactions of +objects throughout the code generation and dynamic loading process. + +Engine Creation +=============== + +In most cases, an EngineBuilder object is used to create an instance of +the MCJIT execution engine. The EngineBuilder takes an llvm::Module +object as an argument to its constructor. The client may then set various +options that we control the later be passed along to the MCJIT engine, +including the selection of MCJIT as the engine type to be created. +Of particular interest is the EngineBuilder::setMCJITMemoryManager +function. If the client does not explicitly create a memory manager at +this time, a default memory manager (specifically SectionMemoryManager) +will be created when the MCJIT engine is instantiated. + +Once the options have been set, a client calls EngineBuilder::create to +create an instance of the MCJIT engine. If the client does not use the +form of this function that takes a TargetMachine as a parameter, a new +TargetMachine will be created based on the target triple associated with +the Module that was used to create the EngineBuilder. + +.. image:: MCJIT-engine-builder.png + +EngineBuilder::create will call the static MCJIT::createJIT function, +passing in its pointers to the module, memory manager and target machine +objects, all of which will subsequently be owned by the MCJIT object. + +The MCJIT class has a member variable, Dyld, which contains an instance of +the RuntimeDyld wrapper class. This member will be used for +communications between MCJIT and the actual RuntimeDyldImpl object that +gets created when an object is loaded. + +.. image:: MCJIT-creation.png + +Upon creation, MCJIT holds a pointer to the Module object that it received +from EngineBuilder but it does not immediately generate code for this +module. Code generation is deferred until either the +MCJIT::finalizeObject method is called explicitly or a function such as +MCJIT::getPointerToFunction is called which requires the code to have been +generated. + +Code Generation +=============== + +When code generation is triggered, as described above, MCJIT will first +attempt to retrieve an object image from its ObjectCache member, if one +has been set. If a cached object image cannot be retrieved, MCJIT will +call its emitObject method. MCJIT::emitObject uses a local PassManager +instance and creates a new ObjectBufferStream instance, both of which it +passes to TargetManager::addPassesToEmitMC before calling PassManager::run +on the Module with which it was created. + +.. image:: MCJIT-load.png + +The PassManager::run call causes the MC code generation mechanisms to emit +a complete relocatable binary object image (either in either ELF or MachO +format, depending on the target) into the ObjectBufferStream object, which +is flushed to complete the process. If an ObjectCache is being used, the +image will be passed to the ObjectCache here. + +At this point, the ObjectBufferStream contains the raw object image. +Before the code can be executed, the code and data sections from this +image must be loaded into suitable memory, relocations must be applied and +memory permission and code cache invalidation (if required) must be completed. + +Object Loading +============== + +Once an object image has been obtained, either through code generation or +having been retrieved from an ObjectCache, it is passed to RuntimeDyld to +be loaded. The RuntimeDyld wrapper class examines the object to determine +its file format and creates an instance of either RuntimeDyldELF or +RuntimeDyldMachO (both of which derive from the RuntimeDyldImpl base +class) and calls the RuntimeDyldImpl::loadObject method to perform that +actual loading. + +.. image:: MCJIT-dyld-load.png + +RuntimeDyldImpl::loadObject begins by creating an ObjectImage instance +from the ObjectBuffer it received. ObjectImage, which wraps the +ObjectFile class, is a helper class which parses the binary object image +and provides access to the information contained in the format-specific +headers, including section, symbol and relocation information. + +RuntimeDyldImpl::loadObject then iterates through the symbols in the +image. Information about common symbols is collected for later use. For +each function or data symbol, the associated section is loaded into memory +and the symbol is stored in a symbol table map data structure. When the +iteration is complete, a section is emitted for the common symbols. + +Next, RuntimeDyldImpl::loadObject iterates through the sections in the +object image and for each section iterates through the relocations for +that sections. For each relocation, it calls the format-specific +processRelocationRef method, which will examine the relocation and store +it in one of two data structures, a section-based relocation list map and +an external symbol relocation map. + +.. image:: MCJIT-load-object.png + +When RuntimeDyldImpl::loadObject returns, all of the code and data +sections for the object will have been loaded into memory allocated by the +memory manager and relocation information will have been prepared, but the +relocations have not yet been applied and the generated code is still not +ready to be executed. + +[Currently (as of August 2013) the MCJIT engine will immediately apply +relocations when loadObject completes. However, this shouldn't be +happening. Because the code may have been generated for a remote target, +the client should be given a chance to re-map the section addresses before +relocations are applied. It is possible to apply relocations multiple +times, but in the case where addresses are to be re-mapped, this first +application is wasted effort.] + +Address Remapping +================= + +At any time after initial code has been generated and before +finalizeObject is called, the client can remap the address of sections in +the object. Typically this is done because the code was generated for an +external process and is being mapped into that process' address space. +The client remaps the section address by calling MCJIT::mapSectionAddress. +This should happen before the section memory is copied to its new +location. + +When MCJIT::mapSectionAddress is called, MCJIT passes the call on to +RuntimeDyldImpl (via its Dyld member). RuntimeDyldImpl stores the new +address in an internal data structure but does not update the code at this +time, since other sections are likely to change. + +When the client is finished remapping section addresses, it will call +MCJIT::finalizeObject to complete the remapping process. + +Final Preparations +================== + +When MCJIT::finalizeObject is called, MCJIT calls +RuntimeDyld::resolveRelocations. This function will attempt to locate any +external symbols and then apply all relocations for the object. + +External symbols are resolved by calling the memory manager's +getPointerToNamedFunction method. The memory manager will return the +address of the requested symbol in the target address space. (Note, this +may not be a valid pointer in the host process.) RuntimeDyld will then +iterate through the list of relocations it has stored which are associated +with this symbol and invoke the resolveRelocation method which, through an +format-specific implementation, will apply the relocation to the loaded +section memory. + +Next, RuntimeDyld::resolveRelocations iterates through the list of +sections and for each section iterates through a list of relocations that +have been saved which reference that symbol and call resolveRelocation for +each entry in this list. The relocation list here is a list of +relocations for which the symbol associated with the relocation is located +in the section associated with the list. Each of these locations will +have a target location at which the relocation will be applied that is +likely located in a different section. + +.. image:: MCJIT-resolve-relocations.png + +Once relocations have been applied as described above, MCJIT calls +RuntimeDyld::getEHFrameSection, and if a non-zero result is returned +passes the section data to the memory manager's registerEHFrames method. +This allows the memory manager to call any desired target-specific +functions, such as registering the EH frame information with a debugger. + +Finally, MCJIT calls the memory manager's finalizeMemory method. In this +method, the memory manager will invalidate the target code cache, if +necessary, and apply final permissions to the memory pages it has +allocated for code and data memory. + diff --git a/docs/Makefile b/docs/Makefile index 122c4b834bba4..d973af583e005 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -19,7 +19,12 @@ $(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in -e 's/@abs_top_srcdir@/../g' \ -e 's/@DOT@/dot/g' \ -e 's/@PACKAGE_VERSION@/mainline/' \ - -e 's/@abs_top_builddir@/../g' > $@ + -e 's/@abs_top_builddir@/../g' \ + -e 's/@enable_searchengine@/NO/g' \ + -e 's/@searchengine_url@//g' \ + -e 's/@enable_server_based_search@/NO/g' \ + -e 's/@enable_external_search@/NO/g' \ + -e 's/@extra_search_mappings@//g' > $@ endif include $(LEVEL)/Makefile.common @@ -77,9 +82,7 @@ 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) $(RM) -rf $(PROJ_OBJ_DIR)/doxygen $(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg $(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg @@ -113,9 +116,7 @@ ocamldoc: regen-ocamldoc regen-ocamldoc: $(Echo) Building ocamldoc documentation - $(Verb) if test -e $(PROJ_OBJ_DIR)/ocamldoc ; then \ - $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc ; \ - fi + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc $(Verb) $(MAKE) -C $(LEVEL)/bindings/ocaml ocamldoc $(Verb) $(MKDIR) $(PROJ_OBJ_DIR)/ocamldoc/html $(Verb) \ diff --git a/docs/MakefileGuide.rst b/docs/MakefileGuide.rst index 3e90907886543..120c108de7860 100644 --- a/docs/MakefileGuide.rst +++ b/docs/MakefileGuide.rst @@ -153,7 +153,7 @@ libraries are the default. For example: LIBRARYNAME = mylib SHARED_LIBRARY = 1 - ARCHIVE_LIBRARY = 1 + BUILD_ARCHIVE = 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 @@ -168,29 +168,9 @@ 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. `Pass documentation -`_ has an example of why you might want to do -this. - -Bitcode Modules -^^^^^^^^^^^^^^^ - -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: - -.. code-block:: makefile - - 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. +intend to be loaded into an tool via the ``-load`` option. :ref:`Pass +documentation ` has an example of why you might +want to do this. Loadable Modules ^^^^^^^^^^^^^^^^ @@ -256,7 +236,7 @@ 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. +built with the ``BUILD_ARCHIVE`` option set. JIT Tools ^^^^^^^^^ @@ -486,9 +466,6 @@ system that tell it what to do for the current directory. 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. @@ -590,13 +567,6 @@ system that tell it what to do for the current directory. setting this variable without also setting ``SHARED_LIBRARY`` will have no effect. -.. _MODULE_NAME: - -``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 @@ -739,12 +709,6 @@ The override variables are given below: ``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. @@ -888,8 +852,6 @@ internal. You should not use these variables under any circumstances. Archive AR.Flags BaseNameSources - BCCompile.C - BCCompile.CXX BCLinkLib C.Flags Compile.C @@ -936,7 +898,6 @@ internal. You should not use these variables under any circumstances. LLVMUsedLibs LocalTargets Module - ObjectsBC ObjectsLO ObjectsO ObjMakefiles diff --git a/docs/NVPTXUsage.rst b/docs/NVPTXUsage.rst index 5451619686d95..a9065ce74ba52 100644 --- a/docs/NVPTXUsage.rst +++ b/docs/NVPTXUsage.rst @@ -66,6 +66,8 @@ function ``@my_kernel`` is callable from host code, but ``@my_fmad`` is not. When compiled, the PTX kernel functions are callable by host-side code. +.. _address_spaces: + Address Spaces -------------- @@ -103,6 +105,25 @@ space in LLVM, so the ``addrspace(N)`` annotation is *required* for global variables. +Triples +------- + +The NVPTX target uses the module triple to select between 32/64-bit code +generation and the driver-compiler interface to use. The triple architecture +can be one of ``nvptx`` (32-bit PTX) or ``nvptx64`` (64-bit PTX). The +operating system should be one of ``cuda`` or ``nvcl``, which determines the +interface used by the generated code to communicate with the driver. Most +users will want to use ``cuda`` as the operating system, which makes the +generated PTX compatible with the CUDA Driver API. + +Example: 32-bit PTX for CUDA Driver API: ``nvptx-nvidia-cuda`` + +Example: 64-bit PTX for CUDA Driver API: ``nvptx64-nvidia-cuda`` + + + +.. _nvptx_intrinsics: + NVPTX Intrinsics ================ @@ -238,6 +259,116 @@ For the full set of NVPTX intrinsics, please see the ``include/llvm/IR/IntrinsicsNVVM.td`` file in the LLVM source tree. +.. _libdevice: + +Linking with Libdevice +====================== + +The CUDA Toolkit comes with an LLVM bitcode library called ``libdevice`` that +implements many common mathematical functions. This library can be used as a +high-performance math library for any compilers using the LLVM NVPTX target. +The library can be found under ``nvvm/libdevice/`` in the CUDA Toolkit and +there is a separate version for each compute architecture. + +For a list of all math functions implemented in libdevice, see +`libdevice Users Guide `_. + +To accomodate various math-related compiler flags that can affect code +generation of libdevice code, the library code depends on a special LLVM IR +pass (``NVVMReflect``) to handle conditional compilation within LLVM IR. This +pass looks for calls to the ``@__nvvm_reflect`` function and replaces them +with constants based on the defined reflection parameters. Such conditional +code often follows a pattern: + +.. code-block:: c++ + + float my_function(float a) { + if (__nvvm_reflect("FASTMATH")) + return my_function_fast(a); + else + return my_function_precise(a); + } + +The default value for all unspecified reflection parameters is zero. + +The ``NVVMReflect`` pass should be executed early in the optimization +pipeline, immediately after the link stage. The ``internalize`` pass is also +recommended to remove unused math functions from the resulting PTX. For an +input IR module ``module.bc``, the following compilation flow is recommended: + +1. Save list of external functions in ``module.bc`` +2. Link ``module.bc`` with ``libdevice.compute_XX.YY.bc`` +3. Internalize all functions not in list from (1) +4. Eliminate all unused internal functions +5. Run ``NVVMReflect`` pass +6. Run standard optimization pipeline + +.. note:: + + ``linkonce`` and ``linkonce_odr`` linkage types are not suitable for the + libdevice functions. It is possible to link two IR modules that have been + linked against libdevice using different reflection variables. + +Since the ``NVVMReflect`` pass replaces conditionals with constants, it will +often leave behind dead code of the form: + +.. code-block:: llvm + + entry: + .. + br i1 true, label %foo, label %bar + foo: + .. + bar: + ; Dead code + .. + +Therefore, it is recommended that ``NVVMReflect`` is executed early in the +optimization pipeline before dead-code elimination. + + +Reflection Parameters +--------------------- + +The libdevice library currently uses the following reflection parameters to +control code generation: + +==================== ====================================================== +Flag Description +==================== ====================================================== +``__CUDA_FTZ=[0,1]`` Use optimized code paths that flush subnormals to zero +==================== ====================================================== + + +Invoking NVVMReflect +-------------------- + +To ensure that all dead code caused by the reflection pass is eliminated, it +is recommended that the reflection pass is executed early in the LLVM IR +optimization pipeline. The pass takes an optional mapping of reflection +parameter name to an integer value. This mapping can be specified as either a +command-line option to ``opt`` or as an LLVM ``StringMap`` object when +programmatically creating a pass pipeline. + +With ``opt``: + +.. code-block:: text + + # opt -nvvm-reflect -nvvm-reflect-list==,= module.bc -o module.reflect.bc + + +With programmatic pass pipeline: + +.. code-block:: c++ + + extern ModulePass *llvm::createNVVMReflectPass(const StringMap& Mapping); + + StringMap ReflectParams; + ReflectParams["__CUDA_FTZ"] = 1; + Passes.add(createNVVMReflectPass(ReflectParams)); + + + Executing PTX ============= @@ -274,3 +405,576 @@ JIT compiling a PTX string to a device binary: For full examples of executing PTX assembly, please see the `CUDA Samples `_ distribution. + + +Common Issues +============= + +ptxas complains of undefined function: __nvvm_reflect +----------------------------------------------------- + +When linking with libdevice, the ``NVVMReflect`` pass must be used. See +:ref:`libdevice` for more information. + + +Tutorial: A Simple Compute Kernel +================================= + +To start, let us take a look at a simple compute kernel written directly in +LLVM IR. The kernel implements vector addition, where each thread computes one +element of the output vector C from the input vectors A and B. To make this +easier, we also assume that only a single CTA (thread block) will be launched, +and that it will be one dimensional. + + +The Kernel +---------- + +.. code-block:: llvm + + 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-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + target triple = "nvptx64-nvidia-cuda" + + ; Intrinsic to read X component of thread ID + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + define void @kernel(float addrspace(1)* %A, + float addrspace(1)* %B, + float addrspace(1)* %C) { + entry: + ; What is my ID? + %id = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + ; Compute pointers into A, B, and C + %ptrA = getelementptr float addrspace(1)* %A, i32 %id + %ptrB = getelementptr float addrspace(1)* %B, i32 %id + %ptrC = getelementptr float addrspace(1)* %C, i32 %id + + ; Read A, B + %valA = load float addrspace(1)* %ptrA, align 4 + %valB = load float addrspace(1)* %ptrB, align 4 + + ; Compute C = A + B + %valC = fadd float %valA, %valB + + ; Store back to C + store float %valC, float addrspace(1)* %ptrC, align 4 + + ret void + } + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1} + + +We can use the LLVM ``llc`` tool to directly run the NVPTX code generator: + +.. code-block:: text + + # llc -mcpu=sm_20 kernel.ll -o kernel.ptx + + +.. note:: + + If you want to generate 32-bit code, change ``p:64:64:64`` to ``p:32:32:32`` + in the module data layout string and use ``nvptx-nvidia-cuda`` as the + target triple. + + +The output we get from ``llc`` (as of LLVM 3.4): + +.. code-block:: text + + // + // Generated by LLVM NVPTX Back-End + // + + .version 3.1 + .target sm_20 + .address_size 64 + + // .globl kernel + // @kernel + .visible .entry kernel( + .param .u64 kernel_param_0, + .param .u64 kernel_param_1, + .param .u64 kernel_param_2 + ) + { + .reg .f32 %f<4>; + .reg .s32 %r<2>; + .reg .s64 %rl<8>; + + // BB#0: // %entry + ld.param.u64 %rl1, [kernel_param_0]; + mov.u32 %r1, %tid.x; + mul.wide.s32 %rl2, %r1, 4; + add.s64 %rl3, %rl1, %rl2; + ld.param.u64 %rl4, [kernel_param_1]; + add.s64 %rl5, %rl4, %rl2; + ld.param.u64 %rl6, [kernel_param_2]; + add.s64 %rl7, %rl6, %rl2; + ld.global.f32 %f1, [%rl3]; + ld.global.f32 %f2, [%rl5]; + add.f32 %f3, %f1, %f2; + st.global.f32 [%rl7], %f3; + ret; + } + + +Dissecting the Kernel +--------------------- + +Now let us dissect the LLVM IR that makes up this kernel. + +Data Layout +^^^^^^^^^^^ + +The data layout string determines the size in bits of common data types, their +ABI alignment, and their storage size. For NVPTX, you should use one of the +following: + +32-bit PTX: + +.. code-block:: llvm + + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + +64-bit PTX: + +.. code-block:: llvm + + 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-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + + +Target Intrinsics +^^^^^^^^^^^^^^^^^ + +In this example, we use the ``@llvm.nvvm.read.ptx.sreg.tid.x`` intrinsic to +read the X component of the current thread's ID, which corresponds to a read +of register ``%tid.x`` in PTX. The NVPTX back-end supports a large set of +intrinsics. A short list is shown below; please see +``include/llvm/IR/IntrinsicsNVVM.td`` for the full list. + + +================================================ ==================== +Intrinsic CUDA Equivalent +================================================ ==================== +``i32 @llvm.nvvm.read.ptx.sreg.tid.{x,y,z}`` threadIdx.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.ctaid.{x,y,z}`` blockIdx.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.ntid.{x,y,z}`` blockDim.{x,y,z} +``i32 @llvm.nvvm.read.ptx.sreg.nctaid.{x,y,z}`` gridDim.{x,y,z} +``void @llvm.cuda.syncthreads()`` __syncthreads() +================================================ ==================== + + +Address Spaces +^^^^^^^^^^^^^^ + +You may have noticed that all of the pointer types in the LLVM IR example had +an explicit address space specifier. What is address space 1? NVIDIA GPU +devices (generally) have four types of memory: + +- Global: Large, off-chip memory +- Shared: Small, on-chip memory shared among all threads in a CTA +- Local: Per-thread, private memory +- Constant: Read-only memory shared across all threads + +These different types of memory are represented in LLVM IR as address spaces. +There is also a fifth address space used by the NVPTX code generator that +corresponds to the "generic" address space. This address space can represent +addresses in any other address space (with a few exceptions). This allows +users to write IR functions that can load/store memory using the same +instructions. Intrinsics are provided to convert pointers between the generic +and non-generic address spaces. + +See :ref:`address_spaces` and :ref:`nvptx_intrinsics` for more information. + + +Kernel Metadata +^^^^^^^^^^^^^^^ + +In PTX, a function can be either a `kernel` function (callable from the host +program), or a `device` function (callable only from GPU code). You can think +of `kernel` functions as entry-points in the GPU program. To mark an LLVM IR +function as a `kernel` function, we make use of special LLVM metadata. The +NVPTX back-end will look for a named metadata node called +``nvvm.annotations``. This named metadata must contain a list of metadata that +describe the IR. For our purposes, we need to declare a metadata node that +assigns the "kernel" attribute to the LLVM IR function that should be emitted +as a PTX `kernel` function. These metadata nodes take the form: + +.. code-block:: text + + metadata !{, metadata !"kernel", i32 1} + +For the previous example, we have: + +.. code-block:: llvm + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1} + +Here, we have a single metadata declaration in ``nvvm.annotations``. This +metadata annotates our ``@kernel`` function with the ``kernel`` attribute. + + +Running the Kernel +------------------ + +Generating PTX from LLVM IR is all well and good, but how do we execute it on +a real GPU device? The CUDA Driver API provides a convenient mechanism for +loading and JIT compiling PTX to a native GPU device, and launching a kernel. +The API is similar to OpenCL. A simple example showing how to load and +execute our vector addition code is shown below. Note that for brevity this +code does not perform much error checking! + +.. note:: + + You can also use the ``ptxas`` tool provided by the CUDA Toolkit to offline + compile PTX to machine code (SASS) for a specific GPU architecture. Such + binaries can be loaded by the CUDA Driver API in the same way as PTX. This + can be useful for reducing startup time by precompiling the PTX kernels. + + +.. code-block:: c++ + + #include + #include + #include + #include "cuda.h" + + + void checkCudaErrors(CUresult err) { + assert(err == CUDA_SUCCESS); + } + + /// main - Program entry point + int main(int argc, char **argv) { + CUdevice device; + CUmodule cudaModule; + CUcontext context; + CUfunction function; + CUlinkState linker; + int devCount; + + // CUDA initialization + checkCudaErrors(cuInit(0)); + checkCudaErrors(cuDeviceGetCount(&devCount)); + checkCudaErrors(cuDeviceGet(&device, 0)); + + char name[128]; + checkCudaErrors(cuDeviceGetName(name, 128, device)); + std::cout << "Using CUDA Device [0]: " << name << "\n"; + + int devMajor, devMinor; + checkCudaErrors(cuDeviceComputeCapability(&devMajor, &devMinor, device)); + std::cout << "Device Compute Capability: " + << devMajor << "." << devMinor << "\n"; + if (devMajor < 2) { + std::cerr << "ERROR: Device 0 is not SM 2.0 or greater\n"; + return 1; + } + + std::ifstream t("kernel.ptx"); + if (!t.is_open()) { + std::cerr << "kernel.ptx not found\n"; + return 1; + } + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + // Create driver context + checkCudaErrors(cuCtxCreate(&context, 0, device)); + + // Create module for object + checkCudaErrors(cuModuleLoadDataEx(&cudaModule, str.c_str(), 0, 0, 0)); + + // Get kernel function + checkCudaErrors(cuModuleGetFunction(&function, cudaModule, "kernel")); + + // Device data + CUdeviceptr devBufferA; + CUdeviceptr devBufferB; + CUdeviceptr devBufferC; + + checkCudaErrors(cuMemAlloc(&devBufferA, sizeof(float)*16)); + checkCudaErrors(cuMemAlloc(&devBufferB, sizeof(float)*16)); + checkCudaErrors(cuMemAlloc(&devBufferC, sizeof(float)*16)); + + float* hostA = new float[16]; + float* hostB = new float[16]; + float* hostC = new float[16]; + + // Populate input + for (unsigned i = 0; i != 16; ++i) { + hostA[i] = (float)i; + hostB[i] = (float)(2*i); + hostC[i] = 0.0f; + } + + checkCudaErrors(cuMemcpyHtoD(devBufferA, &hostA[0], sizeof(float)*16)); + checkCudaErrors(cuMemcpyHtoD(devBufferB, &hostB[0], sizeof(float)*16)); + + + unsigned blockSizeX = 16; + unsigned blockSizeY = 1; + unsigned blockSizeZ = 1; + unsigned gridSizeX = 1; + unsigned gridSizeY = 1; + unsigned gridSizeZ = 1; + + // Kernel parameters + void *KernelParams[] = { &devBufferA, &devBufferB, &devBufferC }; + + std::cout << "Launching kernel\n"; + + // Kernel launch + checkCudaErrors(cuLaunchKernel(function, gridSizeX, gridSizeY, gridSizeZ, + blockSizeX, blockSizeY, blockSizeZ, + 0, NULL, KernelParams, NULL)); + + // Retrieve device data + checkCudaErrors(cuMemcpyDtoH(&hostC[0], devBufferC, sizeof(float)*16)); + + + std::cout << "Results:\n"; + for (unsigned i = 0; i != 16; ++i) { + std::cout << hostA[i] << " + " << hostB[i] << " = " << hostC[i] << "\n"; + } + + + // Clean up after ourselves + delete [] hostA; + delete [] hostB; + delete [] hostC; + + // Clean-up + checkCudaErrors(cuMemFree(devBufferA)); + checkCudaErrors(cuMemFree(devBufferB)); + checkCudaErrors(cuMemFree(devBufferC)); + checkCudaErrors(cuModuleUnload(cudaModule)); + checkCudaErrors(cuCtxDestroy(context)); + + return 0; + } + + +You will need to link with the CUDA driver and specify the path to cuda.h. + +.. code-block:: text + + # clang++ sample.cpp -o sample -O2 -g -I/usr/local/cuda-5.5/include -lcuda + +We don't need to specify a path to ``libcuda.so`` since this is installed in a +system location by the driver, not the CUDA toolkit. + +If everything goes as planned, you should see the following output when +running the compiled program: + +.. code-block:: text + + Using CUDA Device [0]: GeForce GTX 680 + Device Compute Capability: 3.0 + Launching kernel + Results: + 0 + 0 = 0 + 1 + 2 = 3 + 2 + 4 = 6 + 3 + 6 = 9 + 4 + 8 = 12 + 5 + 10 = 15 + 6 + 12 = 18 + 7 + 14 = 21 + 8 + 16 = 24 + 9 + 18 = 27 + 10 + 20 = 30 + 11 + 22 = 33 + 12 + 24 = 36 + 13 + 26 = 39 + 14 + 28 = 42 + 15 + 30 = 45 + +.. note:: + + You will likely see a different device identifier based on your hardware + + +Tutorial: Linking with Libdevice +================================ + +In this tutorial, we show a simple example of linking LLVM IR with the +libdevice library. We will use the same kernel as the previous tutorial, +except that we will compute ``C = pow(A, B)`` instead of ``C = A + B``. +Libdevice provides an ``__nv_powf`` function that we will use. + +.. code-block:: llvm + + 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-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" + target triple = "nvptx64-nvidia-cuda" + + ; Intrinsic to read X component of thread ID + declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + ; libdevice function + declare float @__nv_powf(float, float) + + define void @kernel(float addrspace(1)* %A, + float addrspace(1)* %B, + float addrspace(1)* %C) { + entry: + ; What is my ID? + %id = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() readnone nounwind + + ; Compute pointers into A, B, and C + %ptrA = getelementptr float addrspace(1)* %A, i32 %id + %ptrB = getelementptr float addrspace(1)* %B, i32 %id + %ptrC = getelementptr float addrspace(1)* %C, i32 %id + + ; Read A, B + %valA = load float addrspace(1)* %ptrA, align 4 + %valB = load float addrspace(1)* %ptrB, align 4 + + ; Compute C = pow(A, B) + %valC = call float @__nv_exp2f(float %valA, float %valB) + + ; Store back to C + store float %valC, float addrspace(1)* %ptrC, align 4 + + ret void + } + + !nvvm.annotations = !{!0} + !0 = metadata !{void (float addrspace(1)*, + float addrspace(1)*, + float addrspace(1)*)* @kernel, metadata !"kernel", i32 1}% + + +To compile this kernel, we perform the following steps: + +1. Link with libdevice +2. Internalize all but the public kernel function +3. Run ``NVVMReflect`` and set ``__CUDA_FTZ`` to 0 +4. Optimize the linked module +5. Codegen the module + + +These steps can be performed by the LLVM ``llvm-link``, ``opt``, and ``llc`` +tools. In a complete compiler, these steps can also be performed entirely +programmatically by setting up an appropriate pass configuration (see +:ref:`libdevice`). + +.. code-block:: text + + # llvm-link t2.bc libdevice.compute_20.10.bc -o t2.linked.bc + # opt -internalize -internalize-public-api-list=kernel -nvvm-reflect-list=__CUDA_FTZ=0 -nvvm-reflect -O3 t2.linked.bc -o t2.opt.bc + # llc -mcpu=sm_20 t2.opt.bc -o t2.ptx + +.. note:: + + The ``-nvvm-reflect-list=_CUDA_FTZ=0`` is not strictly required, as any + undefined variables will default to zero. It is shown here for evaluation + purposes. + + +This gives us the following PTX (excerpt): + +.. code-block:: text + + // + // Generated by LLVM NVPTX Back-End + // + + .version 3.1 + .target sm_20 + .address_size 64 + + // .globl kernel + // @kernel + .visible .entry kernel( + .param .u64 kernel_param_0, + .param .u64 kernel_param_1, + .param .u64 kernel_param_2 + ) + { + .reg .pred %p<30>; + .reg .f32 %f<111>; + .reg .s32 %r<21>; + .reg .s64 %rl<8>; + + // BB#0: // %entry + ld.param.u64 %rl2, [kernel_param_0]; + mov.u32 %r3, %tid.x; + ld.param.u64 %rl3, [kernel_param_1]; + mul.wide.s32 %rl4, %r3, 4; + add.s64 %rl5, %rl2, %rl4; + ld.param.u64 %rl6, [kernel_param_2]; + add.s64 %rl7, %rl3, %rl4; + add.s64 %rl1, %rl6, %rl4; + ld.global.f32 %f1, [%rl5]; + ld.global.f32 %f2, [%rl7]; + setp.eq.f32 %p1, %f1, 0f3F800000; + setp.eq.f32 %p2, %f2, 0f00000000; + or.pred %p3, %p1, %p2; + @%p3 bra BB0_1; + bra.uni BB0_2; + BB0_1: + mov.f32 %f110, 0f3F800000; + st.global.f32 [%rl1], %f110; + ret; + BB0_2: // %__nv_isnanf.exit.i + abs.f32 %f4, %f1; + setp.gtu.f32 %p4, %f4, 0f7F800000; + @%p4 bra BB0_4; + // BB#3: // %__nv_isnanf.exit5.i + abs.f32 %f5, %f2; + setp.le.f32 %p5, %f5, 0f7F800000; + @%p5 bra BB0_5; + BB0_4: // %.critedge1.i + add.f32 %f110, %f1, %f2; + st.global.f32 [%rl1], %f110; + ret; + BB0_5: // %__nv_isinff.exit.i + + ... + + BB0_26: // %__nv_truncf.exit.i.i.i.i.i + mul.f32 %f90, %f107, 0f3FB8AA3B; + cvt.rzi.f32.f32 %f91, %f90; + mov.f32 %f92, 0fBF317200; + fma.rn.f32 %f93, %f91, %f92, %f107; + mov.f32 %f94, 0fB5BFBE8E; + fma.rn.f32 %f95, %f91, %f94, %f93; + mul.f32 %f89, %f95, 0f3FB8AA3B; + // inline asm + ex2.approx.ftz.f32 %f88,%f89; + // inline asm + add.f32 %f96, %f91, 0f00000000; + ex2.approx.f32 %f97, %f96; + mul.f32 %f98, %f88, %f97; + setp.lt.f32 %p15, %f107, 0fC2D20000; + selp.f32 %f99, 0f00000000, %f98, %p15; + setp.gt.f32 %p16, %f107, 0f42D20000; + selp.f32 %f110, 0f7F800000, %f99, %p16; + setp.eq.f32 %p17, %f110, 0f7F800000; + @%p17 bra BB0_28; + // BB#27: + fma.rn.f32 %f110, %f110, %f108, %f110; + BB0_28: // %__internal_accurate_powf.exit.i + setp.lt.f32 %p18, %f1, 0f00000000; + setp.eq.f32 %p19, %f3, 0f3F800000; + and.pred %p20, %p18, %p19; + @!%p20 bra BB0_30; + bra.uni BB0_29; + BB0_29: + mov.b32 %r9, %f110; + xor.b32 %r10, %r9, -2147483648; + mov.b32 %f110, %r10; + BB0_30: // %__nv_powf.exit + st.global.f32 [%rl1], %f110; + ret; + } + diff --git a/docs/Passes.rst b/docs/Passes.rst index d279eca3afb65..029e472bcd37d 100644 --- a/docs/Passes.rst +++ b/docs/Passes.rst @@ -476,7 +476,7 @@ transformation obviously invalidates the CFG, but can update forward dominator ------------------------------------------------- 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 +SelectionDAG-based code generation. This works around limitations in its basic-block-at-a-time approach. It should eventually be removed. ``-constmerge``: Merge Duplicate Global Constants @@ -490,7 +490,7 @@ string is available. ``-constprop``: Simple constant propagation ------------------------------------------- -This file implements constant propagation and merging. It looks for +This pass 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: @@ -505,8 +505,8 @@ becomes i32 3 NOTE: this pass has a habit of making definitions be dead. It is a good idea -to to run a :ref:`Dead Instruction Elimination ` pass sometime -after running this pass. +to run a :ref:`Dead Instruction Elimination ` pass sometime after +running this pass. .. _passes-dce: @@ -1037,7 +1037,7 @@ as: * Proves conditional branches to be unconditional Note that this pass has a habit of making definitions be dead. It is a good -idea to to run a :ref:`DCE ` pass sometime after running this pass. +idea to run a :ref:`DCE ` pass sometime after running this pass. ``-simplify-libcalls``: Simplify well-known library calls --------------------------------------------------------- diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst index efab10cd13a5d..6fdea1f941725 100644 --- a/docs/Phabricator.rst +++ b/docs/Phabricator.rst @@ -56,7 +56,7 @@ to upload your patch): To upload a new patch: * Click *Differential*. -* Click *Create Revision*. +* Click *Create Diff*. * Paste the text diff or upload the patch file. Note that TODO * Leave the drop down on *Create a new Revision...* and click *Continue*. @@ -68,7 +68,7 @@ To upload a new patch: To submit an updated patch: * Click *Differential*. -* Click *Create Revision*. +* Click *Create Diff*. * Paste the updated diff. * Select the review you want to from the *Attach To* dropdown and click *Continue*. diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index 7864165617a03..99aa5c7877b4e 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -1172,7 +1172,7 @@ 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 +elements out of (linear time), unless you use its "pop_back" method, which is faster. ``SetVector`` is an adapter class that defaults to using ``std::vector`` and a @@ -2080,7 +2080,7 @@ the ``llvm_stop_multithreaded()`` call. You can also use the 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 +``llvm_start_multithreaded()`` or ``llvm_stop_multithreaded``. It is the client's responsibility to enforce this isolation. The return value of ``llvm_start_multithreaded()`` indicates the success or @@ -2421,7 +2421,7 @@ place the ``vptr`` in the first word of the instances.) The Core LLVM Class Hierarchy Reference ======================================= -``#include "llvm/Type.h"`` +``#include "llvm/IR/Type.h"`` header source: `Type.h `_ @@ -2524,7 +2524,7 @@ Important Derived Types The ``Module`` class -------------------- -``#include "llvm/Module.h"`` +``#include "llvm/IR/Module.h"`` header source: `Module.h `_ @@ -2611,7 +2611,7 @@ Important Public Members of the ``Module`` class The ``Value`` class ------------------- -``#include "llvm/Value.h"`` +``#include "llvm/IR/Value.h"`` header source: `Value.h `_ @@ -2702,7 +2702,7 @@ Important Public Members of the ``Value`` class The ``User`` class ------------------ -``#include "llvm/User.h"`` +``#include "llvm/IR/User.h"`` header source: `User.h `_ @@ -2748,7 +2748,7 @@ interface and through an iterator based interface. The ``Instruction`` class ------------------------- -``#include "llvm/Instruction.h"`` +``#include "llvm/IR/Instruction.h"`` header source: `Instruction.h `_ @@ -2896,7 +2896,7 @@ Important Subclasses of Constant The ``GlobalValue`` class ------------------------- -``#include "llvm/GlobalValue.h"`` +``#include "llvm/IR/GlobalValue.h"`` header source: `GlobalValue.h `_ @@ -2955,7 +2955,7 @@ Important Public Members of the ``GlobalValue`` class The ``Function`` class ---------------------- -``#include "llvm/Function.h"`` +``#include "llvm/IR/Function.h"`` header source: `Function.h `_ @@ -3063,7 +3063,7 @@ Important Public Members of the ``Function`` The ``GlobalVariable`` class ---------------------------- -``#include "llvm/GlobalVariable.h"`` +``#include "llvm/IR/GlobalVariable.h"`` header source: `GlobalVariable.h `_ @@ -3121,7 +3121,7 @@ Important Public Members of the ``GlobalVariable`` class The ``BasicBlock`` class ------------------------ -``#include "llvm/BasicBlock.h"`` +``#include "llvm/IR/BasicBlock.h"`` header source: `BasicBlock.h `_ diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index f2afdc9efe625..0874f3a3c5220 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,5 +1,5 @@ ====================== -LLVM 3.3 Release Notes +LLVM 3.4 Release Notes ====================== .. contents:: @@ -9,7 +9,7 @@ Introduction ============ This document contains the release notes for the LLVM Compiler Infrastructure, -release 3.3. Here we describe the status of LLVM, including major improvements +release 3.4. Here we describe the status of LLVM, including major improvements from the previous release, improvements in various subprojects of LLVM, and some of the current users of the code. All LLVM releases may be downloaded from the `LLVM releases web site `_. @@ -28,280 +28,210 @@ page `_. Non-comprehensive list of changes in this release ================================================= -* The CellSPU port has been removed. It can still be found in older versions. +* This is expected to be the last release of LLVM which compiles using a C++98 + toolchain. We expect to start using some C++11 features in LLVM and other + sub-projects starting after this release. That said, we are committed to + supporting a reasonable set of modern C++ toolchains as the host compiler on + all of the platforms. This will at least include Visual Studio 2012 on + Windows, and Clang 3.1 or GCC 4.7.x on Mac and Linux. The final set of + compilers (and the C++11 features they support) is not set in stone, but we + wanted users of LLVM to have a heads up that the next release will involve + a substantial change in the host toolchain requirements. -* The IR-level extended linker APIs (for example, to link bitcode files out of - archives) have been removed. Any existing clients of these features should - move to using a linker with integrated LTO support. +* The regression tests now fail if any command in a pipe fails. To disable it in + a directory, just add ``config.pipefail = False`` to its ``lit.local.cfg``. + See :doc:`Lit ` for the details. -* LLVM and Clang's documentation has been migrated to the `Sphinx - `_ documentation generation system which uses - easy-to-write reStructuredText. See `llvm/docs/README.txt` for more - information. +* Support for exception handling has been removed from the old JIT. Use MCJIT + if you need EH support. -* TargetTransformInfo (TTI) is a new interface that can be used by IR-level - passes to obtain target-specific information, such as the costs of - instructions. Only "Lowering" passes such as LSR and the vectorizer are - allowed to use the TTI infrastructure. +* The R600 backend is not marked experimental anymore and is built by default. -* We've improved the X86 and ARM cost model. +* APFloat::isNormal() was renamed to APFloat::isFiniteNonZero() and + APFloat::isIEEENormal() was renamed to APFloat::isNormal(). This ensures that + APFloat::isNormal() conforms to IEEE-754R-2008. -* The Attributes classes have been completely rewritten and expanded. They now - support not only enumerated attributes and alignments, but "string" - attributes, which are useful for passing information to code generation. See - :doc:`HowToUseAttributes` for more details. +* The library call simplification pass has been removed. Its functionality + has been integrated into the instruction combiner and function attribute + marking passes. -* TableGen's syntax for instruction selection patterns has been simplified. - Instead of specifying types indirectly with register classes, you should now - specify types directly in the input patterns. See ``SparcInstrInfo.td`` for - examples of the new syntax. The old syntax using register classes still - works, but it will be removed in a future LLVM release. +* Support for building using Visual Studio 2008 has been dropped. Use VS 2010 + or later instead. For more information, see the `Getting Started using Visual + Studio `_ page. -* MCJIT now supports exception handling. Support for it in the old jit will be - removed in the 3.4 release. +* The Loop Vectorizer that was previously enabled for -O3 is now enabled for + -Os and -O2. -* Command line options can now be grouped into categories which are shown in - the output of ``-help``. See :ref:`grouping options into categories`. +* The new SLP Vectorizer is now enabled by default. -* The appearance of command line options in ``-help`` that are inherited by - linking with libraries that use the LLVM Command line support library can now - be modified at runtime. See :ref:`cl::getRegisteredOptions`. +* llvm-ar now uses the new Object library and produces archives and + symbol tables in the gnu format. -AArch64 target --------------- - -We've added support for AArch64, ARM's 64-bit architecture. Development is still -in fairly early stages, but we expect successful compilation when: +* FileCheck now allows specifing -check-prefix multiple times. This + helps reduce duplicate check lines when using multiple RUN lines. -- compiling standard compliant C99 and C++03 with Clang; -- using Linux as a target platform; -- where code + static data doesn't exceed 4GB in size (heap allocated data has - no limitation). +* The bitcast instruction no longer allows casting between pointers + with different address spaces. To achieve this, use the new + addrspacecast instruction. -Some additional functionality is also implemented, notably DWARF debugging, -GNU-style thread local storage and inline assembly. +* Different sized pointers for different address spaces should now + generally work. This is primarily useful for GPU targets. -Hexagon Target --------------- +* OCaml bindings have been significantly extended to cover almost all of the + LLVM libraries. -Removed support for legacy hexagonv2 and hexagonv3 processor architectures which -are no longer in use. Currently supported architectures are hexagonv4 and -hexagonv5. +Mips Target +----------- -Mips target --------------- +Support for the MIPS SIMD Architecture (MSA) has been added. MSA is supported +through inline assembly, intrinsics with the prefix '__builtin_msa', and normal +code generation. -New features and improvements: - -- Clang driver - - Support for Sourcery CodeBench Mips toolchain directories tree. - - Support for new command line options including: - - -mxgot/-mno-xgot - - -EL / -EB - - -mmicromips / -mno-micromips - - -msingle-float / -mdouble-float - - -mabi=32 (o32 abi) and -mabi=64 (n64 abi) - - Previously, options such as -mips16, -mmicromips, -mdsp and -mdspr2 were - not passed to the assembler. This issue has been fixed. - -- A number of changes have been made to improve the quality of DSP-ASE code - generation. - - Multiply and multiply-accumulate instructions can now use all four - accumulators. - - Instruction selection patterns have been added so that DSP instructions - are emitted without having to use builtins. - -- Delay slot filler pass can now search successor blocks for instructions to - fill delay slots (use option -disable-mips-df-succbb-search=false). +For more information on MSA (including documentation for the instruction set), +see the `MIPS SIMD page at Imagination Technologies +`_ PowerPC Target -------------- -New features and improvements: - -- PowerPC now supports an assembly parser. -- Support added for thread-local storage. 64-bit ELF subtarget only. -- Support added for medium and large code model (-mcmodel=medium,large). - Medium code model is now the default. 64-bit ELF subtarget only. -- Improved register allocation (fewer reserved registers). -- 64-bit atomic load and store are now supported. -- Improved code generation for unaligned memory accesses of scalar types. -- Improved performance of floating-point divide and square root - with -ffast-math. -- Support for predicated returns. -- Improved code generation for comparisons. -- Support added for inline setjmp and longjmp. -- Support added for many instructions introduced in PowerISA 2.04, 2.05, - and 2.06. -- Improved spill code for vector registers. -- Support added for -mno-altivec. -- ABI compatibility fixes for complex parameters, 128-bit integer parameters, - and varargs functions. 64-bit ELF subtarget only. - -Loop Vectorizer ---------------- - -We've continued the work on the loop vectorizer. The loop vectorizer now -has the following features: +Changes in the PowerPC backend include: -- Loops with unknown trip counts. -- Runtime checks of pointers. -- Reductions, Inductions. -- Min/Max reductions of integers. -- If Conversion. -- Pointer induction variables. -- Reverse iterators. -- Vectorization of mixed types. -- Vectorization of function calls. -- Partial unrolling during vectorization. +* fast-isel support (for faster -O0 code generation) +* many improvements to the builtin assembler +* support for generating unaligned (Altivec) vector loads +* support for generating the fcpsgn instruction +* generate frin for round() (not nearbyint() and rint(), which had been done only in fast-math mode) +* improved instruction scheduling for embedded cores (such as the A2) +* improved prologue/epilogue generation (especially in 32-bit mode) +* support for dynamic stack alignment (and dynamic stack allocations with large alignments) +* improved generation of counter-register-based loops +* bug fixes -The loop vectorizer is now enabled by default for -O3. - -SLP Vectorizer --------------- - -LLVM now has a new SLP vectorizer. The new SLP vectorizer is not enabled by -default but can be enabled using the clang flag ``-fslp-vectorize``. The -BB-vectorizer can also be enabled using the command line flag -``-fslp-vectorize-aggressive``. - -R600 Backend +SPARC Target ------------ -The R600 backend was added in this release, it supports AMD GPUs (HD2XXX - -HD7XXX). This backend is used in AMD's Open Source graphics / compute drivers -which are developed as part of the `Mesa3D `_ project. +The SPARC backend got many improvements, namely + +* experimental SPARC V9 backend +* JIT support for SPARC +* fp128 support +* exception handling +* TLS support +* leaf functions optimization +* bug fixes SystemZ/s390x Backend --------------------- -LLVM and clang now support IBM's z/Architecture. At present this support -is restricted to GNU/Linux (GNU triplet s390x-linux-gnu) and requires -z10 or greater. +LLVM and clang can now optimize for zEnterprise z196 and zEnterprise EC12 +targets. In clang these targets are selected using ``-march=z196`` and +``-march=zEC12`` respectively. +External Open Source Projects Using LLVM 3.4 +============================================ -Sub-project Status Update -========================= - -In addition to the core LLVM 3.3 distribution of production-quality compiler -infrastructure, the LLVM project includes sub-projects that use the LLVM core -and share the same distribution license. This section provides updates on these -sub-projects. - - -DragonEgg: GCC front-ends, LLVM back-end ----------------------------------------- - -`DragonEgg `_ is a -`GCC plugin `_ that replaces GCC's optimizers -and code generators with LLVM's. It works with gcc-4.5, 4.6, 4.7 and 4.8, can -target the x86-32/x86-64 and ARM processor families, and has been successfully -used on the Darwin, FreeBSD, KFreeBSD, Linux and OpenBSD platforms. It fully -supports Ada, C, C++ and Fortran. It has partial support for Go, Java, Obj-C -and Obj-C++. Note that gcc-4.6 is the best supported version, and that Ada in -particular doesn't work well with gcc-4.7 and newer. - -The `3.3 release `_ has the following notable changes. - -- supports gcc-4.8 (requires gcc-4.8.1 or newer) -- object files can be written directly using LLVM's integrated assembler -- produces saner debug info -- bitfields can now contain arbitrary scalar types (useful for Ada) - - -LLDB: Low Level Debugger ------------------------- - -`LLDB `_ is a ground-up implementation of a command-line -debugger, as well as a debugger API that can be used from scripts and other -applications. LLDB uses the following components of the LLVM core distribution -to support the latest language features and target support: - -- the Clang parser for high-quality parsing of C, C++ and Objective C -- the LLVM disassembler -- the LLVM JIT compiler (MCJIT) for expression evaluation +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 3.4. -The `3.3 release `_ has the following notable changes. +DXR +--- -Linux Features: +`DXR `_ is Mozilla's code search and navigation +tool, aimed at making sense of large projects like Firefox. It supports +full-text and regex searches as well as structural queries like "Find all the +callers of this function." Behind the scenes, it uses a custom trigram index, +the re2 library, and structural data collected by a clang compiler plugin. -- Support for watchpoints -- vim integration for lldb commands and program status using a `vim plug-in - `_ -- Improved register support including vector registers -- Builds with cmake/ninja/auto-tools/clang 3.3/gcc 4.6 +LDC - the LLVM-based D compiler +------------------------------- -Linux Improvements: +`D `_ is a language with C-like syntax and static typing. It +pragmatically combines efficiency, control, and modeling power, with safety and +programmer productivity. D supports powerful concepts like Compile-Time Function +Execution (CTFE) and Template Meta-Programming, provides an innovative approach +to concurrency and offers many classical paradigms. -- Debugging multi-threaded programs -- Debugging i386 programs -- Process list, attach and fork -- Expression evaluation +`LDC `_ uses the frontend from the reference compiler +combined with LLVM as backend to produce efficient native code. LDC targets +x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux/PPC64. +Ports to other architectures like ARM and AArch64 are underway. +LibBeauty +--------- -External Open Source Projects Using LLVM 3.3 -============================================ +The `LibBeauty `_ decompiler and reverse +engineering tool currently utilises the LLVM disassembler and the LLVM IR +Builder. The current aim of the project is to take a x86_64 binary ``.o`` file +as input, and produce an equivalent LLVM IR ``.bc`` or ``.ll`` file as +output. Support for ARM binary ``.o`` file as input will be added later. -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 3.3. +Likely +------ +`Likely `_ is an open source domain specific +language for image recognition. Algorithms are just-in-time compiled using +LLVM's MCJIT infrastructure to execute on single or multi-threaded CPUs as well +as OpenCL SPIR or CUDA enabled GPUs. Likely exploits the observation that while +image processing and statistical learning kernels must be written generically +to handle any matrix datatype, at runtime they tend to be executed repeatedly +on the same type. Portable Computing Language (pocl) ---------------------------------- -In addition to producing an easily portable open source OpenCL implementation, -another major goal of `pocl `_ is improving -performance portability of OpenCL programs with compiler optimizations, reducing -the need for target-dependent manual optimizations. An important part of pocl is -a set of LLVM passes used to statically parallelize multiple work-items with the -kernel compiler, even in the presence of work-group barriers. This enables -static parallelization of the fine-grained static concurrency in the work groups -in multiple ways. +In addition to producing an easily portable open source OpenCL +implementation, another major goal of `pocl `_ +is improving performance portability of OpenCL programs with +compiler optimizations, reducing the need for target-dependent manual +optimizations. An important part of pocl is a set of LLVM passes used to +statically parallelize multiple work-items with the kernel compiler, even in +the presence of work-group barriers. This enables static parallelization of +the fine-grained static concurrency in the work groups in multiple ways. + +Portable Native Client (PNaCl) +------------------------------ + +`Portable Native Client (PNaCl) `_ +is a Chrome initiative to bring the performance and low-level control of native +code to modern web browsers, without sacrificing the security benefits and +portability of web applications. PNaCl works by compiling native C and C++ code +to an intermediate representation using the LLVM clang compiler. This +intermediate representation is a subset of LLVM bytecode that is wrapped into a +portable executable, which can be hosted on a web server like any other website +asset. When the site is accessed, Chrome fetches and translates the portable +executable into an architecture-specific machine code optimized directly for +the underlying device. PNaCl lets developers compile their code once to run on +any hardware platform and embed their PNaCl application in any website, +enabling developers to directly leverage the power of the underlying CPU and +GPU. TTA-based Co-design Environment (TCE) ------------------------------------- -`TCE `_ is a toolset for designing new processors based -on the Transport triggered architecture (TTA). The toolset provides a complete -co-design flow from C/C++ programs down to synthesizable VHDL/Verilog and -parallel program binaries. Processor customization points include the register -files, function units, supported operations, and the interconnection network. - -TCE uses Clang and LLVM for C/C++/OpenCL 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. - -Just-in-time Adaptive Decoder Engine (Jade) -------------------------------------------- - -`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 (`Orcc -`_) and requires it to translate the RVC-CAL standard -library of video coding tools into an LLVM assembly code. +`TCE `_ is a toolset for designing new +exposed datapath processors based on the Transport triggered architecture (TTA). +The toolset provides a complete co-design flow from C/C++ +programs down to synthesizable VHDL/Verilog and parallel program binaries. +Processor customization points include the register files, function units, +supported operations, and the interconnection network. -LDC - the LLVM-based D compiler -------------------------------- +TCE uses Clang and LLVM for C/C++/OpenCL 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 processors and +loads them in to the compiler backend as runtime libraries to avoid +per-target recompilation of larger parts of the compiler chain. -`D `_ is a language with C-like syntax and static typing. It -pragmatically combines efficiency, control, and modeling power, with safety and -programmer productivity. D supports powerful concepts like Compile-Time Function -Execution (CTFE) and Template Meta-Programming, provides an innovative approach -to concurrency and offers many classical paradigms. +WebCL Validator +--------------- -`LDC `_ uses the frontend from the reference compiler -combined with LLVM as backend to produce efficient native code. LDC targets -x86/x86_64 systems like Linux, OS X and Windows and also Linux/PPC64. Ports to -other architectures like ARM are underway. +`WebCL Validator `_ implements +validation for WebCL C language which is a subset of OpenCL ES 1.1. Validator +checks the correctness of WebCL C, and implements memory protection for it as a +source-2-source transformation. The transformation converts WebCL to memory +protected OpenCL. The protected OpenCL cannot access any memory ranges which +were not allocated for it, and its memory is always initialized to prevent +information leakage from other programs. Additional Information @@ -316,4 +246,3 @@ going into the ``llvm/docs/`` directory in the LLVM tree. If you have any questions or comments about LLVM, please feel free to contact us via the `mailing lists `_. - diff --git a/docs/ReleaseProcess.rst b/docs/ReleaseProcess.rst new file mode 100644 index 0000000000000..0836b6e92a3b1 --- /dev/null +++ b/docs/ReleaseProcess.rst @@ -0,0 +1,212 @@ +============================= +How To Validate a New Release +============================= + +.. contents:: + :local: + :depth: 1 + +Introduction +============ + +This document contains information about testing the release candidates that will +ultimately be the next LLVM release. For more information on how to manage the +actual release, please refer to :doc:`HowToReleaseLLVM`. + +Overview of the Release Process +------------------------------- + +Once the release process starts, the Release Manager will ask for volunteers, +and it'll be the role of each volunteer to: + +* Test and benchmark the previous release + +* Test and benchmark each release candidate, comparing to the previous release and candidates + +* Identify, reduce and report every regression found during tests and benchmarks + +* Make sure the critical bugs get fixed and merged to the next release candidate + +Not all bugs or regressions are show-stoppers and it's a bit of a grey area what +should be fixed before the next candidate and what can wait until the next release. + +It'll depend on: + +* The severity of the bug, how many people it affects and if it's a regression or a + known bug. Known bugs are "unsupported features" and some bugs can be disabled if + they have been implemented recently. + +* The stage in the release. Less critical bugs should be considered to be fixed between + RC1 and RC2, but not so much at the end of it. + +* If it's a correctness or a performance regression. Performance regression tends to be + taken more lightly than correctness. + +.. _scripts: + +Scripts +======= + +The scripts are in the ``utils/release`` directory. + +test-release.sh +--------------- + +This script will check-out, configure and compile LLVM+Clang (+ most add-ons, +like ``compiler-rt``, ``libcxx`` and ``clang-extra-tools``) in three stages, and +will test the final stage. It'll have installed the final binaries on the +Phase3/Releasei(+Asserts) directory, and that's the one you should use for the +test-suite and other external tests. + +To run the script on a specific release candidate run:: + + ./test-release.sh \ + -release 3.4 \ + -rc 1 \ + -triple x86_64-apple-darwin \ + -no-64bit \ + -test-asserts \ + -no-compare-files + +Each system will require different options. For instance, x86_64 will obviously not need +``-no-64bit`` while 32-bit systems will, or the script will fail. + +The important flags to get right are: + +* On the pre-release, you should change ``-rc 1`` to ``-final``. On RC2, change it to ``-rc 2`` and so on. + +* On non-release testing, you can use ``-final`` in conjunction with ``-no-checkout``, but you'll have to + create the ``final`` directory by hand and link the correct source dir to ``final/llvm.src``. + +* For release candidates, you need ``-test-asserts``, or it won't create a "Release+Asserts" directory, + which is needed for release testing and benchmarking. This will take twice as long. + +* On the final candidate you just need Release builds, and that's the binary directory you'll have to pack. + +This script builds three phases of Clang+LLVM twice each (Release and Release+Asserts), so use +screen or nohup to avoid headaches, since it'll take a long time. + +Use the ``--help`` option to see all the options and chose it according to your needs. + + +findRegressions-nightly.py +-------------------------- + +TODO + +.. _test-suite: + +Test Suite +========== + +.. contents:: + :local: + +Follow the `LNT Quick Start Guide `__ link on how to set-up the test-suite + +The binary location you'll have to use for testing is inside the ``rcN/Phase3/Release+Asserts/llvmCore-REL-RC.install``. +Link that directory to an easier location and run the test-suite. + +An example on the run command line, assuming you created a link from the correct +install directory to ``~/devel/llvm/install``:: + + ./sandbox/bin/python sandbox/bin/lnt runtest \ + nt \ + -j4 \ + --sandbox sandbox \ + --test-suite ~/devel/llvm/test/test-suite \ + --cc ~/devel/llvm/install/bin/clang \ + --cxx ~/devel/llvm/install/bin/clang++ + +It should have no new regressions, compared to the previous release or release candidate. You don't need to fix +all the bugs in the test-suite, since they're not necessarily meant to pass on all architectures all the time. This is +due to the nature of the result checking, which relies on direct comparison, and most of the time, the failures are +related to bad output checking, rather than bad code generation. + +If the errors are in LLVM itself, please report every single regression found as blocker, and all the other bugs +as important, but not necessarily blocking the release to proceed. They can be set as "known failures" and to be +fix on a future date. + +.. _pre-release-process: + +Pre-Release Process +=================== + +.. contents:: + :local: + +When the release process is announced on the mailing list, you should prepare +for the testing, by applying the same testing you'll do on the release candidates, +on the previous release. + +You should: + +* Download the previous release sources from http://llvm.org/releases/download.html. + +* Run the test-release.sh script on ``final`` mode (change ``-rc 1`` to ``-final``). + +* Once all three stages are done, it'll test the final stage. + +* Using the ``Phase3/Release+Asserts/llvmCore-MAJ.MIN-final.install`` base, run the test-suite. + +If the final phase's ``make check-all`` failed, it's a good idea to also test the +intermediate stages by going on the obj directory and running ``make check-all`` to find +if there's at least one stage that passes (helps when reducing the error for bug report +purposes). + +.. _release-process: + +Release Process +=============== + +.. contents:: + :local: + +When the Release Manager sends you the release candidate, download all sources, +unzip on the same directory (there will be sym-links from the appropriate places +to them), and run the release test as above. + +You should: + +* Download the current candidate sources from where the release manager points you + (ex. http://llvm.org/pre-releases/3.3/rc1/). + +* Repeat the steps above with ``-rc 1``, ``-rc 2`` etc modes and run the test-suite + the same way. + +* Compare the results, report all errors on Bugzilla and publish the binary blob + where the release manager can grab it. + +Once the release manages announces that the latest candidate is the good one, you +have to pack the ``Release`` (no Asserts) install directory on ``Phase3`` and that +will be the official binary. + +* Rename (or link) ``clang+llvm-REL-ARCH-ENV`` to the .install directory + +* Tar that into the same name with ``.tar.gz`` extensioan from outside the directory + +* Make it available for the release manager to download + +.. _bug-reporting: + +Bug Reporting Process +===================== + +.. contents:: + :local: + +If you found regressions or failures when comparing a release candidate with the +previous release, follow the rules below: + +* Critical bugs on compilation should be fixed as soon as possible, possibly before + releasing the binary blobs. + +* Check-all tests should be fixed before the next release candidate, but can wait + until the test-suite run is finished. + +* Bugs in the test suite or unimportant check-all tests can be fixed in between + release candidates. + +* New features or recent big changes, when close to the release, should have done + in a way that it's easy to disable. If they misbehave, prefer disabling them than + releasing an unstable (but untested) binary package. diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst index 857479508a5e2..a1d8110637f6b 100644 --- a/docs/SourceLevelDebugging.rst +++ b/docs/SourceLevelDebugging.rst @@ -169,9 +169,7 @@ 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 appended at the end that is source-language specific. 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 @@ -192,10 +190,7 @@ the simple data types ``i32``, ``i1``, ``float``, ``double``, ``mdstring`` and ``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.) +does not restrict the use of the information supplied to DWARF targets. The details of the various descriptors follow. @@ -205,13 +200,10 @@ Compile unit descriptors .. code-block:: llvm !0 = metadata !{ - i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit) - i32, ;; Unused field. + i32, ;; Tag = 17 (DW_TAG_compile_unit) + metadata, ;; Source directory (including trailing slash) & file pair 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 @@ -219,18 +211,21 @@ Compile unit descriptors metadata ;; List of retained types metadata ;; List of subprograms metadata ;; List of global variables + metadata ;; List of imported entities + metadata ;; Split debug filename } 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. +``DW_LANG_Cobol74``, etc), a reference to a metadata node containing a pair of +strings for the source file name and the working directory, as well as 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. These descriptors are collected by a named metadata ``!llvm.dbg.cu``. They -keep track of subprograms, global variables and type information. +keep track of subprograms, global variables, type information, and imported +entities (declarations and namespaces). .. _format_files: @@ -240,10 +235,8 @@ File descriptors .. code-block:: llvm !0 = metadata !{ - i32, ;; Tag = 41 + LLVMDebugVersion (DW_TAG_file_type) - metadata, ;; Source file name - metadata, ;; Source file directory (includes trailing slash) - metadata ;; Unused + i32, ;; Tag = 41 (DW_TAG_file_type) + metadata, ;; Source directory (including trailing slash) & file pair } These descriptors contain information for a file. Global variables and top @@ -261,7 +254,7 @@ Global variable descriptors .. code-block:: llvm !1 = metadata !{ - i32, ;; Tag = 52 + LLVMDebugVersion (DW_TAG_variable) + i32, ;; Tag = 52 (DW_TAG_variable) i32, ;; Unused field. metadata, ;; Reference to context descriptor metadata, ;; Name @@ -272,7 +265,8 @@ Global variable descriptors 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 + {}*, ;; Reference to the global variable + metadata, ;; The static member declaration, if any } These descriptors provide debug information about globals variables. They @@ -287,13 +281,12 @@ Subprogram descriptors .. code-block:: llvm !2 = metadata !{ - i32, ;; Tag = 46 + LLVMDebugVersion (DW_TAG_subprogram) - i32, ;; Unused field. + i32, ;; Tag = 46 (DW_TAG_subprogram) + metadata, ;; Source directory (including trailing slash) & file pair 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) @@ -302,7 +295,7 @@ Subprogram descriptors i32, ;; Index into a virtual function metadata, ;; indicates which base type contains the vtable pointer for the ;; derived class - i32, ;; Flags - Artifical, Private, Protected, Explicit, Prototyped. + i32, ;; Flags - Artificial, Private, Protected, Explicit, Prototyped. i1, ;; isOptimized Function * , ;; Pointer to LLVM function metadata, ;; Lists function template parameters @@ -321,11 +314,11 @@ Block descriptors .. code-block:: llvm !3 = metadata !{ - i32, ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block) + i32, ;; Tag = 11 (DW_TAG_lexical_block) + metadata,;; Source directory (including trailing slash) & file pair metadata,;; Reference to context descriptor i32, ;; Line number i32, ;; Column number - metadata,;; Reference to source file i32 ;; Unique ID to identify blocks from a template function } @@ -336,9 +329,9 @@ lexical blocks at same depth. .. code-block:: llvm !3 = metadata !{ - i32, ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block) + i32, ;; Tag = 11 (DW_TAG_lexical_block) + metadata,;; Source directory (including trailing slash) & file pair metadata ;; Reference to the scope we're annotating with a file change - metadata,;; Reference to the file the scope is enclosed in. } This descriptor provides a wrapper around a lexical scope to handle file @@ -352,10 +345,10 @@ Basic type descriptors .. code-block:: llvm !4 = metadata !{ - i32, ;; Tag = 36 + LLVMDebugVersion (DW_TAG_base_type) + i32, ;; Tag = 36 (DW_TAG_base_type) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) 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 @@ -396,9 +389,9 @@ Derived type descriptors !5 = metadata !{ i32, ;; Tag (see below) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) 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 @@ -459,9 +452,9 @@ Composite type descriptors !6 = metadata !{ i32, ;; Tag (see below) + metadata, ;; Source directory (including trailing slash) & file pair (may be null) 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 @@ -469,7 +462,10 @@ Composite type descriptors i32, ;; Flags metadata, ;; Reference to type derived from metadata, ;; Reference to array of member descriptors - i32 ;; Runtime languages + i32, ;; Runtime languages + metadata, ;; Base type containing the vtable pointer for this type + metadata, ;; Template parameters + metadata ;; A unique identifier for type uniquing purpose (may be null) } These descriptors are used to define types that are composed of 0 or more @@ -531,7 +527,7 @@ Subrange descriptors .. code-block:: llvm !42 = metadata !{ - i32, ;; Tag = 33 + LLVMDebugVersion (DW_TAG_subrange_type) + i32, ;; Tag = 33 (DW_TAG_subrange_type) i64, ;; Low value i64 ;; High value } @@ -550,7 +546,7 @@ Enumerator descriptors .. code-block:: llvm !6 = metadata !{ - i32, ;; Tag = 40 + LLVMDebugVersion (DW_TAG_enumerator) + i32, ;; Tag = 40 (DW_TAG_enumerator) metadata, ;; Name i64 ;; Value } @@ -654,59 +650,86 @@ Compiled to LLVM, this function would be represented like this: .. code-block:: llvm - define void @foo() nounwind ssp { + define void @foo() #0 { entry: - %X = alloca i32, align 4 ; [#uses=4] - %Y = alloca i32, align 4 ; [#uses=4] - %Z = alloca i32, align 4 ; [#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 ; [#uses=1] - %tmp1 = load i32* %Y, !dbg !16 ; [#uses=1] - %add = add nsw i32 %tmp, %tmp1, !dbg !16 ; [#uses=1] - store i32 %add, i32* %Z, !dbg !16 - %tmp2 = load i32* %Y, !dbg !17 ; [#uses=1] - store i32 %tmp2, i32* %X, !dbg !17 - ret void, !dbg !18 + %X = alloca i32, align 4 + %Y = alloca i32, align 4 + %Z = alloca i32, align 4 + call void @llvm.dbg.declare(metadata !{i32* %X}, metadata !10), !dbg !12 + ; [debug line = 2:7] [debug variable = X] + store i32 21, i32* %X, align 4, !dbg !12 + call void @llvm.dbg.declare(metadata !{i32* %Y}, metadata !13), !dbg !14 + ; [debug line = 3:7] [debug variable = Y] + store i32 22, i32* %Y, align 4, !dbg !14 + call void @llvm.dbg.declare(metadata !{i32* %Z}, metadata !15), !dbg !17 + ; [debug line = 5:9] [debug variable = Z] + store i32 23, i32* %Z, align 4, !dbg !17 + %0 = load i32* %X, align 4, !dbg !18 + [debug line = 6:5] + store i32 %0, i32* %Z, align 4, !dbg !18 + %1 = load i32* %Y, align 4, !dbg !19 + [debug line = 8:3] + store i32 %1, i32* %X, align 4, !dbg !19 + ret void, !dbg !20 } - 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} + ; Function Attrs: nounwind readnone + declare void @llvm.dbg.declare(metadata, metadata) #1 + + attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" + "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" + "no-infs-fp-math"="false" "no-nans-fp-math"="false" + "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" + "use-soft-float"="false" } + attributes #1 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!8} + !llvm.ident = !{!9} + + !0 = metadata !{i32 786449, metadata !1, i32 12, + metadata !"clang version 3.4 (trunk 193128) (llvm/trunk 193139)", + i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, + metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] \ + [/private/tmp/foo.c] \ + [DW_LANG_C99] + !1 = metadata !{metadata !"t.c", metadata !"/private/tmp"} + !2 = metadata !{i32 0} + !3 = metadata !{metadata !4} + !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", + metadata !"foo", metadata !"", i32 1, metadata !6, + i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, + void ()* @foo, null, null, metadata !2, i32 1} + ; [ DW_TAG_subprogram ] [line 1] [def] [foo] + !5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] \ + [/private/tmp/t.c] + !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, + i64 0, i32 0, null, metadata !7, i32 0, null, null, null} + ; [ DW_TAG_subroutine_type ] \ + [line 0, size 0, align 0, offset 0] [from ] + !7 = metadata !{null} + !8 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} + !9 = metadata !{metadata !"clang version 3.4 (trunk 193128) (llvm/trunk 193139)"} + !10 = metadata !{i32 786688, metadata !4, metadata !"X", metadata !5, i32 2, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [X] \ + [line 2] + !11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, + i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] \ + [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] + !12 = metadata !{i32 2, i32 0, metadata !4, null} + !13 = metadata !{i32 786688, metadata !4, metadata !"Y", metadata !5, i32 3, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [Y] \ + [line 3] + !14 = metadata !{i32 3, i32 0, metadata !4, null} + !15 = metadata !{i32 786688, metadata !16, metadata !"Z", metadata !5, i32 5, + metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [Z] \ + [line 5] + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} \ + ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] + !17 = metadata !{i32 5, i32 0, metadata !16, null} + !18 = metadata !{i32 6, i32 0, metadata !16, null} + !19 = metadata !{i32 8, i32 0, metadata !4, null} ; [ DW_TAG_imported_declaration ] + !20 = metadata !{i32 9, i32 0, metadata !4, null} This example illustrates a few important details about LLVM debugging information. In particular, it shows how the ``llvm.dbg.declare`` intrinsic and @@ -716,25 +739,26 @@ variable definitions, and the code used to implement the function. .. code-block:: llvm - call void @llvm.dbg.declare(metadata, metadata !0), !dbg !7 + call void @llvm.dbg.declare(metadata !{i32* %X}, metadata !10), !dbg !12 + ; [debug line = 2:7] [debug variable = X] The first intrinsic ``%llvm.dbg.declare`` encodes debugging information for the -variable ``X``. The metadata ``!dbg !7`` attached to the intrinsic provides +variable ``X``. The metadata ``!dbg !12`` attached to the intrinsic provides scope information for the variable ``X``. .. code-block:: llvm - !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 ] + !12 = metadata !{i32 2, i32 0, metadata !4, null} + !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", + metadata !"foo", metadata !"", i32 1, metadata !6, + i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, + void ()* @foo, null, null, metadata !2, i32 1} + ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -Here ``!7`` is metadata providing location information. It has four fields: +Here ``!12`` 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 +is null otherwise. In this example, scope is encoded by ``!4``, a :ref:`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``. @@ -743,20 +767,22 @@ Now lets take another example. .. code-block:: llvm - call void @llvm.dbg.declare(metadata, metadata !12), !dbg !14 + call void @llvm.dbg.declare(metadata !{i32* %Z}, metadata !15), !dbg !17 + ; [debug line = 5:9] [debug variable = Z] -The second intrinsic ``%llvm.dbg.declare`` encodes debugging information for -variable ``Z``. The metadata ``!dbg !14`` attached to the intrinsic provides +The third intrinsic ``%llvm.dbg.declare`` encodes debugging information for +variable ``Z``. The metadata ``!dbg !17`` attached to the intrinsic provides scope information for the variable ``Z``. .. code-block:: llvm - !13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ] - !14 = metadata !{i32 5, i32 9, metadata !13, null} + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} + ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] + !17 = metadata !{i32 5, i32 0, metadata !16, 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. +Here ``!15`` indicates that ``Z`` is declared at line number 5 and +column number 0 inside of lexical scope ``!16``. The lexical scope itself +resides inside of subprogram ``!4`` described above. The scope information attached with each instruction provides a straightforward way to find instructions covered by a scope. @@ -805,36 +831,44 @@ 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 + !0 = metadata !{ + i32 786449, ;; Tag + metadata !1, ;; File/directory name + i32 4, ;; Language Id + metadata !"clang version 3.4 ", + i1 false, ;; Optimized compile unit + metadata !"", ;; Compiler flags + i32 0, ;; Runtime version + metadata !2, ;; Enumeration types + metadata !2, ;; Retained types + metadata !3, ;; Subprograms + metadata !2, ;; Global variables + metadata !2, ;; Imported entities (declarations and namespaces) + metadata !"" ;; Split debug filename + } ;; ;; 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 + metadata !"/Users/mine/sources" + } + !5 = metadata !{ + i32 786473, ;; Tag + metadata !1 } ;; ;; Define the file for the file "/Users/mine/sources/Myheader.h" ;; - !3 = metadata !{ - i32 524329, ;; Tag - metadata !"Myheader.h" + !14 = metadata !{ + i32 786473, ;; Tag + metadata !15 + } + !15 = metadata !{ + metadata !"./MyHeader.h", metadata !"/Users/mine/sources", - metadata !2 ;; Compile unit } ... @@ -890,7 +924,9 @@ a C/C++ front-end would generate the following descriptors: metadata !1, ;; Enum Types metadata !1, ;; Retained Types metadata !1, ;; Subprograms - metadata !3 ;; Global Variables + metadata !3, ;; Global Variables + metadata !1, ;; Imported entities + "", ;; Split debug filename } ; [ DW_TAG_compile_unit ] ;; The Array of Global Variables @@ -898,14 +934,10 @@ a C/C++ front-end would generate the following descriptors: metadata !4 } - !4 = metadata !{ - metadata !5 - } - ;; ;; Define the global variable itself. ;; - !5 = metadata !{ + !4 = metadata !{ i32 786484, ;; Tag i32 0, ;; Unused null, ;; Unused @@ -917,17 +949,20 @@ a C/C++ front-end would generate the following descriptors: metadata !7, ;; Type i32 0, ;; IsLocalToUnit i32 1, ;; IsDefinition - i32* @MyGlobal ;; LLVM-IR Value + i32* @MyGlobal, ;; LLVM-IR Value + null ;; Static member declaration } ; [ DW_TAG_variable ] ;; ;; Define the file ;; - !6 = metadata !{ - i32 786473, ;; Tag + !5 = metadata !{ metadata !"foo.cpp", ;; File metadata !"/Volumes/Data/tmp", ;; Directory - null ;; Unused + } + !6 = metadata !{ + i32 786473, ;; Tag + metadata !5 ;; Unused } ; [ DW_TAG_file_type ] ;; @@ -936,8 +971,8 @@ a C/C++ front-end would generate the following descriptors: !7 = metadata !{ i32 786468, ;; Tag null, ;; Unused - metadata !"int", ;; Name null, ;; Unused + metadata !"int", ;; Name i32 0, ;; Line i64 32, ;; Size in Bits i64 32, ;; Align in Bits @@ -962,18 +997,15 @@ a C/C++ front-end would generate the following descriptors: .. code-block:: llvm ;; - ;; 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.) + ;; Define the anchor for subprograms. ;; !6 = metadata !{ - i32 524334, ;; Tag - i32 0, ;; Unused + i32 786484, ;; Tag + metadata !1, ;; File 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 @@ -984,7 +1016,9 @@ a C/C++ front-end would generate the following descriptors: i32 0, ;; Flags i1 false, ;; True if this function is optimized Function *, ;; Pointer to llvm::Function - null ;; Function template parameters + null, ;; Function template parameters + null, ;; List of function variables (emitted when optimizing) + 1 ;; Line number of the opening '{' of the function } ;; ;; Define the subprogram itself. @@ -1004,10 +1038,10 @@ bool .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"bool", ;; Name - metadata !1, ;; File i32 0, ;; Line number i64 8, ;; Size in Bits i64 8, ;; Align in Bits @@ -1022,10 +1056,10 @@ char .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"char", ;; Name - metadata !1, ;; File i32 0, ;; Line number i64 8, ;; Size in Bits i64 8, ;; Align in Bits @@ -1040,10 +1074,10 @@ unsigned char .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"unsigned char", - metadata !1, ;; File i32 0, ;; Line number i64 8, ;; Size in Bits i64 8, ;; Align in Bits @@ -1058,10 +1092,10 @@ short .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"short int", - metadata !1, ;; File i32 0, ;; Line number i64 16, ;; Size in Bits i64 16, ;; Align in Bits @@ -1076,10 +1110,10 @@ unsigned short .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"short unsigned int", - metadata !1, ;; File i32 0, ;; Line number i64 16, ;; Size in Bits i64 16, ;; Align in Bits @@ -1094,10 +1128,10 @@ int .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"int", ;; Name - metadata !1, ;; File i32 0, ;; Line number i64 32, ;; Size in Bits i64 32, ;; Align in Bits @@ -1112,10 +1146,10 @@ unsigned int .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"unsigned int", - metadata !1, ;; File i32 0, ;; Line number i64 32, ;; Size in Bits i64 32, ;; Align in Bits @@ -1130,10 +1164,10 @@ long long .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"long long int", - metadata !1, ;; File i32 0, ;; Line number i64 64, ;; Size in Bits i64 64, ;; Align in Bits @@ -1148,10 +1182,10 @@ unsigned long long .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"long long unsigned int", - metadata !1, ;; File i32 0, ;; Line number i64 64, ;; Size in Bits i64 64, ;; Align in Bits @@ -1166,10 +1200,10 @@ float .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"float", - metadata !1, ;; File i32 0, ;; Line number i64 32, ;; Size in Bits i64 32, ;; Align in Bits @@ -1184,10 +1218,10 @@ double .. code-block:: llvm !2 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"double",;; Name - metadata !1, ;; File i32 0, ;; Line number i64 64, ;; Size in Bits i64 64, ;; Align in Bits @@ -1213,10 +1247,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define the typedef "IntPtr". ;; !2 = metadata !{ - i32 524310, ;; Tag + i32 786454, ;; Tag + metadata !3, ;; File metadata !1, ;; Context metadata !"IntPtr", ;; Name - metadata !3, ;; File i32 0, ;; Line number i64 0, ;; Size in bits i64 0, ;; Align in bits @@ -1228,10 +1262,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define the pointer type. ;; !4 = metadata !{ - i32 524303, ;; Tag - metadata !1, ;; Context + i32 786447, ;; Tag + null, ;; File + null, ;; Context metadata !"", ;; Name - metadata !1, ;; File i32 0, ;; Line number i64 64, ;; Size in bits i64 64, ;; Align in bits @@ -1243,13 +1277,13 @@ a C/C++ front-end would generate the following descriptors: ;; Define the const type. ;; !5 = metadata !{ - i32 524326, ;; Tag - metadata !1, ;; Context + i32 786470, ;; Tag + null, ;; File + null, ;; Context metadata !"", ;; Name - metadata !1, ;; File i32 0, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits + i64 0, ;; Size in bits + i64 0, ;; Align in bits i64 0, ;; Offset in bits i32 0, ;; Flags metadata !6 ;; Derived From type @@ -1258,16 +1292,16 @@ a C/C++ front-end would generate the following descriptors: ;; Define the int type. ;; !6 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; 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 + i32 5 ;; Encoding } C/C++ struct/union types @@ -1291,10 +1325,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define basic type for unsigned int. ;; !5 = metadata !{ - i32 524324, ;; Tag - metadata !1, ;; Context + i32 786468, ;; Tag + null, ;; File + null, ;; Context metadata !"unsigned int", - metadata !1, ;; File i32 0, ;; Line number i64 32, ;; Size in Bits i64 32, ;; Align in Bits @@ -1306,10 +1340,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define composite type for struct Color. ;; !2 = metadata !{ - i32 524307, ;; Tag - metadata !1, ;; Context - metadata !"Color", ;; Name + i32 786451, ;; Tag metadata !1, ;; Compile unit + null, ;; Context + metadata !"Color", ;; Name i32 1, ;; Line number i64 96, ;; Size in bits i64 32, ;; Align in bits @@ -1317,17 +1351,19 @@ a C/C++ front-end would generate the following descriptors: i32 0, ;; Flags null, ;; Derived From metadata !3, ;; Elements - i32 0 ;; Runtime Language + i32 0, ;; Runtime Language + null, ;; Base type containing the vtable pointer for this type + null ;; Template parameters } ;; ;; Define the Red field. ;; !4 = metadata !{ - i32 524301, ;; Tag + i32 786445, ;; Tag + metadata !1, ;; File metadata !1, ;; Context metadata !"Red", ;; Name - metadata !1, ;; File i32 2, ;; Line number i64 32, ;; Size in bits i64 32, ;; Align in bits @@ -1340,10 +1376,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define the Green field. ;; !6 = metadata !{ - i32 524301, ;; Tag + i32 786445, ;; Tag + metadata !1, ;; File metadata !1, ;; Context metadata !"Green", ;; Name - metadata !1, ;; File i32 3, ;; Line number i64 32, ;; Size in bits i64 32, ;; Align in bits @@ -1356,10 +1392,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define the Blue field. ;; !7 = metadata !{ - i32 524301, ;; Tag + i32 786445, ;; Tag + metadata !1, ;; File metadata !1, ;; Context metadata !"Blue", ;; Name - metadata !1, ;; File i32 4, ;; Line number i64 32, ;; Size in bits i64 32, ;; Align in bits @@ -1394,10 +1430,10 @@ a C/C++ front-end would generate the following descriptors: ;; Define composite type for enum Trees ;; !2 = metadata !{ - i32 524292, ;; Tag + i32 786436, ;; Tag + metadata !1, ;; File metadata !1, ;; Context metadata !"Trees", ;; Name - metadata !1, ;; File i32 1, ;; Line number i64 32, ;; Size in bits i64 32, ;; Align in bits @@ -1416,17 +1452,17 @@ a C/C++ front-end would generate the following descriptors: ;; ;; Define Spruce enumerator. ;; - !4 = metadata !{i32 524328, metadata !"Spruce", i64 100} + !4 = metadata !{i32 786472, metadata !"Spruce", i64 100} ;; ;; Define Oak enumerator. ;; - !5 = metadata !{i32 524328, metadata !"Oak", i64 200} + !5 = metadata !{i32 786472, metadata !"Oak", i64 200} ;; ;; Define Maple enumerator. ;; - !6 = metadata !{i32 524328, metadata !"Maple", i64 300} + !6 = metadata !{i32 786472, metadata !"Maple", i64 300} Debugging information format ============================ diff --git a/docs/TestingGuide.rst b/docs/TestingGuide.rst index 79cedee764f70..c9a35cd746348 100644 --- a/docs/TestingGuide.rst +++ b/docs/TestingGuide.rst @@ -21,9 +21,9 @@ tests. Requirements ============ -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. +In order to use the LLVM testing infrastructure, you will need all of the +software required to build LLVM, as well as `Python `_ 2.5 or +later. LLVM testing infrastructure organization ======================================== @@ -120,12 +120,14 @@ can run the LLVM and Clang tests simultaneously using: % make check-all -To run the tests with Valgrind (Memcheck by default), just append -``VG=1`` to the commands above, e.g.: +To run the tests with Valgrind (Memcheck by default), use the ``LIT_ARGS`` make +variable to pass the required options to lit. For example, you can use: .. code-block:: bash - % make check VG=1 + % make check LIT_ARGS="-v --vg --vg-leak" + +to enable testing with valgrind and with leak checking enabled. 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 @@ -275,6 +277,66 @@ This test will fail if placed into a ``download`` directory. To make your tests robust, always use ``opt ... < %s`` in the RUN line. :program:`opt` does not output a ``ModuleID`` when input comes from stdin. +Platform-Specific Tests +----------------------- + +Whenever adding tests that require the knowledge of a specific platform, +either related to code generated, specific output or back-end features, +you must make sure to isolate the features, so that buildbots that +run on different architectures (and don't even compile all back-ends), +don't fail. + +The first problem is to check for target-specific output, for example sizes +of structures, paths and architecture names, for example: + +* Tests containing Windows paths will fail on Linux and vice-versa. +* Tests that check for ``x86_64`` somewhere in the text will fail anywhere else. +* Tests where the debug information calculates the size of types and structures. + +Also, if the test rely on any behaviour that is coded in any back-end, it must +go in its own directory. So, for instance, code generator tests for ARM go +into ``test/CodeGen/ARM`` and so on. Those directories contain a special +``lit`` configuration file that ensure all tests in that directory will +only run if a specific back-end is compiled and available. + +For instance, on ``test/CodeGen/ARM``, the ``lit.local.cfg`` is: + +.. code-block:: python + + config.suffixes = ['.ll', '.c', '.cpp', '.test'] + targets = set(config.root.targets_to_build.split()) + if not 'ARM' in targets: + config.unsupported = True + +Other platform-specific tests are those that depend on a specific feature +of a specific sub-architecture, for example only to Intel chips that support ``AVX2``. + +For instance, ``test/CodeGen/X86/psubus.ll`` tests three sub-architecture +variants: + +.. code-block:: llvm + + ; RUN: llc -mcpu=core2 < %s | FileCheck %s -check-prefix=SSE2 + ; RUN: llc -mcpu=corei7-avx < %s | FileCheck %s -check-prefix=AVX1 + ; RUN: llc -mcpu=core-avx2 < %s | FileCheck %s -check-prefix=AVX2 + +And the checks are different: + +.. code-block:: llvm + + ; SSE2: @test1 + ; SSE2: psubusw LCPI0_0(%rip), %xmm0 + ; AVX1: @test1 + ; AVX1: vpsubusw LCPI0_0(%rip), %xmm0, %xmm0 + ; AVX2: @test1 + ; AVX2: vpsubusw LCPI0_0(%rip), %xmm0, %xmm0 + +So, if you're testing for a behaviour that you know is platform-specific or +depends on special features of sub-architectures, you must add the specific +triple, test with the specific FileCheck and put it into the specific +directory that will filter out all other architectures. + + Variables and substitutions --------------------------- diff --git a/docs/Vectorizers.rst b/docs/Vectorizers.rst index d565c2122c9a0..61ebca2bb529f 100644 --- a/docs/Vectorizers.rst +++ b/docs/Vectorizers.rst @@ -7,11 +7,13 @@ Auto-Vectorization in LLVM LLVM has two vectorizers: The :ref:`Loop Vectorizer `, which operates on Loops, and the :ref:`SLP Vectorizer -`, which optimizes straight-line code. These vectorizers +`. These vectorizers focus on different optimization opportunities and use different techniques. The SLP vectorizer merges multiple scalars that are found in the code into -vectors while the Loop Vectorizer widens instructions in the original loop -to operate on multiple consecutive loop iterations. +vectors while the Loop Vectorizer widens instructions in loops +to operate on multiple consecutive iterations. + +Both the Loop Vectorizer and the SLP Vectorizer are enabled by default. .. _loop-vectorizer: @@ -21,9 +23,8 @@ The Loop Vectorizer Usage ----- -LLVM's Loop Vectorizer is now enabled by default for -O3. -We plan to enable parts of the Loop Vectorizer on -O2 and -Os in future releases. -The vectorizer can be disabled using the command line: +The Loop Vectorizer is enabled by default, but it can be disabled +through clang using the command line flag: .. code-block:: console @@ -302,10 +303,9 @@ Details ------- The goal of SLP vectorization (a.k.a. superword-level parallelism) is -to combine similar independent instructions within simple control-flow regions -into vector instructions. Memory accesses, arithemetic operations, comparison -operations and some math functions can all be vectorized using this technique -(subject to the capabilities of the target architecture). +to combine similar independent instructions +into vector instructions. Memory accesses, arithmetic operations, comparison +operations, PHI-nodes, can all be vectorized using this technique. For example, the following function performs very similar operations on its inputs (a1, b1) and (a2, b2). The basic-block vectorizer may combine these @@ -318,18 +318,17 @@ into vector operations. A[1] = a2*(a2 + b2)/b2 + 50*b2/a2; } -The SLP-vectorizer has two phases, bottom-up, and top-down. The top-down vectorization -phase is more aggressive, but takes more time to run. +The SLP-vectorizer processes the code bottom-up, across basic blocks, in search of scalars to combine. Usage ------ -The SLP Vectorizer is not enabled by default, but it can be enabled +The SLP Vectorizer is enabled by default, but it can be disabled through clang using the command line flag: .. code-block:: console - $ clang -fslp-vectorize file.c + $ clang -fno-slp-vectorize file.c LLVM has a second basic block vectorization phase which is more compile-time intensive (The BB vectorizer). This optimization @@ -339,24 +338,3 @@ can be enabled through clang using the command line flag: $ clang -fslp-vectorize-aggressive file.c - -The SLP vectorizer is in early development stages but can already vectorize -and accelerate many programs in the LLVM test suite. - -======================= ============ -Benchmark Name Gain -======================= ============ -Misc/flops-7 -32.70% -Misc/matmul_f64_4x4 -23.23% -Olden/power -21.45% -Misc/flops-4 -14.90% -ASC_Sequoia/AMGmk -13.85% -TSVC/LoopRerolling-flt -11.76% -Misc/flops-6 -9.70% -Misc/flops-5 -8.54% -Misc/flops -8.12% -TSVC/NodeSplitting-dbl -6.96% -Misc-C++/sphereflake -6.74% -Ptrdist/yacr2 -6.31% -======================= ============ - diff --git a/docs/WritingAnLLVMBackend.rst b/docs/WritingAnLLVMBackend.rst index a03a5e42c22d0..35a2d164a9093 100644 --- a/docs/WritingAnLLVMBackend.rst +++ b/docs/WritingAnLLVMBackend.rst @@ -1,6 +1,6 @@ -================================ -Writing an LLVM Compiler Backend -================================ +======================= +Writing an LLVM Backend +======================= .. toctree:: :hidden: @@ -911,6 +911,103 @@ 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. +Instruction Operand Name Mapping +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen will also generate a function called getNamedOperandIdx() which +can be used to look up an operand's index in a MachineInstr based on its +TableGen name. Setting the UseNamedOperandTable bit in an instruction's +TableGen definition will add all of its operands to an enumeration in the +llvm::XXX:OpName namespace and also add an entry for it into the OperandMap +table, which can be queried using getNamedOperandIdx() + +.. code-block:: llvm + + int DstIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::dst); // => 0 + int BIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::b); // => 1 + int CIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::c); // => 2 + int DIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::d); // => -1 + + ... + +The entries in the OpName enum are taken verbatim from the TableGen definitions, +so operands with lowercase names will have lower case entries in the enum. + +To include the getNamedOperandIdx() function in your backend, you will need +to define a few preprocessor macros in XXXInstrInfo.cpp and XXXInstrInfo.h. +For example: + +XXXInstrInfo.cpp: + +.. code-block:: c++ + + #define GET_INSTRINFO_NAMED_OPS // For getNamedOperandIdx() function + #include "XXXGenInstrInfo.inc" + +XXXInstrInfo.h: + +.. code-block:: c++ + + #define GET_INSTRINFO_OPERAND_ENUM // For OpName enum + #include "XXXGenInstrInfo.inc" + + namespace XXX { + int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); + } // End namespace XXX + +Instruction Operand Types +^^^^^^^^^^^^^^^^^^^^^^^^^ + +TableGen will also generate an enumeration consisting of all named Operand +types defined in the backend, in the llvm::XXX::OpTypes namespace. +Some common immediate Operand types (for instance i8, i32, i64, f32, f64) +are defined for all targets in ``include/llvm/Target/Target.td``, and are +available in each Target's OpTypes enum. Also, only named Operand types appear +in the enumeration: anonymous types are ignored. +For example, the X86 backend defines ``brtarget`` and ``brtarget8``, both +instances of the TableGen ``Operand`` class, which represent branch target +operands: + +.. code-block:: llvm + + def brtarget : Operand; + def brtarget8 : Operand; + +This results in: + +.. code-block:: c++ + + namespace X86 { + namespace OpTypes { + enum OperandType { + ... + brtarget, + brtarget8, + ... + i32imm, + i64imm, + ... + OPERAND_TYPE_LIST_END + } // End namespace OpTypes + } // End namespace X86 + +In typical TableGen fashion, to use the enum, you will need to define a +preprocessor macro: + +.. code-block:: c++ + + #define GET_INSTRINFO_OPERAND_TYPES_ENUM // For OpTypes enum + #include "XXXGenInstrInfo.inc" + + +Instruction Scheduling +---------------------- + +Instruction itineraries can be queried using MCDesc::getSchedClass(). The +value can be named by an enumemation in llvm::XXX::Sched namespace generated +by TableGen in XXXGenInstrInfo.inc. The name of the schedule classes are +the same as provided in XXXSchedule.td plus a default NoItinerary class. + Instruction Relation Mapping ---------------------------- diff --git a/docs/WritingAnLLVMPass.rst b/docs/WritingAnLLVMPass.rst index b10d98f87e2ba..f9cb4fe80fd39 100644 --- a/docs/WritingAnLLVMPass.rst +++ b/docs/WritingAnLLVMPass.rst @@ -96,7 +96,7 @@ Start out with: .. code-block:: c++ #include "llvm/Pass.h" - #include "llvm/Function.h" + #include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" Which are needed because we are writing a `Pass @@ -131,7 +131,7 @@ Next, we declare our pass itself: struct Hello : public FunctionPass { -This declares a "``Hello``" class that is a subclass of `FunctionPass +This declares a "``Hello``" class that is a subclass of :ref:`FunctionPass `. The different builtin pass subclasses are described in detail :ref:`later `, but for now, know that ``FunctionPass`` operates on a function at a time. @@ -184,7 +184,7 @@ As a whole, the ``.cpp`` file looks like: .. code-block:: c++ #include "llvm/Pass.h" - #include "llvm/Function.h" + #include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -454,7 +454,7 @@ external functions. To be explicit, ``FunctionPass`` subclasses are not allowed to: -#. Modify a ``Function`` other than the one currently being processed. +#. Inspect or modify a ``Function`` other than the one currently being processed. #. Add or remove ``Function``\ s from the current ``Module``. #. Add or remove global variables from the current ``Module``. #. Maintain state across invocations of:ref:`runOnFunction diff --git a/docs/YamlIO.rst b/docs/YamlIO.rst index ac50292f4a812..3ecd03afb24d8 100644 --- a/docs/YamlIO.rst +++ b/docs/YamlIO.rst @@ -109,7 +109,7 @@ ScalarEnumerationTraits on that type and define the enumeration() method: As with all YAML I/O template specializations, the ScalarEnumerationTraits is used for both reading and writing YAML. That is, the mapping between in-memory enum -values and the YAML string representation is only in place. +values and the YAML string representation is only in one place. This assures that the code for writing and parsing of YAML stays in sync. To specify a YAML mappings, you define a specialization on @@ -353,7 +353,7 @@ had the following bit flags defined: flagsRound = 8 }; - LLVM_YAML_UNIQUE_TYPE(MyFlags, uint32_t) + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyFlags) To support reading and writing of MyFlags, you specialize ScalarBitSetTraits<> on MyFlags and provide the bit values and their names. @@ -408,7 +408,7 @@ some time format (e.g. 4-May-2012 10:30pm). YAML I/O has a way to support custom formatting and parsing of scalar types by specializing ScalarTraits<> on your data type. When writing, YAML I/O will provide the native type and your specialization must create a temporary llvm::StringRef. When reading, -YAML I/O will provide a llvm::StringRef of scalar and your specialization +YAML I/O will provide an llvm::StringRef of scalar and your specialization must convert that to your native data type. An outline of a custom scalar type looks like: @@ -533,7 +533,7 @@ coordinates into polar when reading YAML. y(polar.distance * sin(polar.angle)) { } Polar denormalize(IO &) { - return Polar(sqrt(x*x+y*y, arctan(x,y)); + return Polar(sqrt(x*x+y*y), arctan(x,y)); } float x; @@ -549,7 +549,7 @@ coordinates into polar when reading YAML. }; When writing YAML, the local variable "keys" will be a stack allocated -instance of NormalizedPolar, constructed from the suppled polar object which +instance of NormalizedPolar, constructed from the supplied polar object which initializes it x and y fields. The mapRequired() methods then write out the x and y values as key/value pairs. @@ -633,6 +633,20 @@ This works for both reading and writing. For example: }; +Tags +---- + +The YAML syntax supports tags as a way to specify the type of a node before +it is parsed. This allows dynamic types of nodes. But the YAML I/O model uses +static typing, so there are limits to how you can use tags with the YAML I/O +model. Recently, we added support to YAML I/O for checking/setting the optional +tag on a map. Using this functionality it is even possbile to support differnt +mappings, as long as they are convertable. + +To check a tag, inside your mapping() method you can use io.mapTag() to specify +what the tag should be. This will also add that tag when writing yaml. + + Sequence ======== @@ -646,7 +660,7 @@ llvm::yaml::SequenceTraits on T and implement two methods: template <> struct SequenceTraits { static size_t size(IO &io, MySeq &list) { ... } - static MySeqEl element(IO &io, MySeq &list, size_t index) { ... } + static MySeqEl &element(IO &io, MySeq &list, size_t index) { ... } }; The size() method returns how many elements are currently in your sequence. @@ -669,7 +683,7 @@ add "static const bool flow = true;". For instance: template <> struct SequenceTraits { static size_t size(IO &io, MyList &list) { ... } - static MyListEl element(IO &io, MyList &list, size_t index) { ... } + static MyListEl &element(IO &io, MyList &list, size_t index) { ... } // The existence of this member causes YAML I/O to use a flow sequence static const bool flow = true; diff --git a/docs/conf.py b/docs/conf.py index 0ac3b7836b9e4..d71f46e99917d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,9 +47,9 @@ copyright = u'2003-2013, LLVM Project' # built documents. # # The short X.Y version. -version = '3.3' +version = '3.4' # The full version, including alpha/beta/rc tags. -release = '3.3' +release = '3.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in index 20de0773f403a..0ed686b9349fb 100644 --- a/docs/doxygen.cfg.in +++ b/docs/doxygen.cfg.in @@ -1,3 +1,4 @@ + # Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system @@ -1068,7 +1069,7 @@ FORMULA_TRANSPARENT = YES # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = @enable_searchengine@ # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client @@ -1078,7 +1079,15 @@ SEARCHENGINE = NO # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. -SERVER_BASED_SEARCH = NO +SERVER_BASED_SEARCH = @enable_server_based_search@ + +SEARCHENGINE_URL = @searchengine_url@ + +EXTERNAL_SEARCH = @enable_external_search@ + +EXTERNAL_SEARCH_ID = llvm + +EXTRA_SEARCH_MAPPINGS = @extra_search_mappings@ #--------------------------------------------------------------------------- # configuration options related to the LaTeX output diff --git a/docs/index.rst b/docs/index.rst index 6b182dac56072..62766f10342fe 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -66,6 +66,7 @@ representation. CMake HowToBuildOnARM + HowToCrossCompileLLVM CommandGuide/index GettingStarted GettingStartedVS @@ -82,6 +83,7 @@ representation. Passes YamlIO GetElementPtr + MCJITDesignAndImplementation :doc:`GettingStarted` Discusses how to get up and running quickly with the LLVM infrastructure. @@ -95,6 +97,9 @@ representation. :doc:`HowToBuildOnARM` Notes on building and testing LLVM/Clang on ARM. +:doc:`HowToCrossCompileLLVM` + Notes on cross-building and testing LLVM/Clang. + :doc:`GettingStartedVS` An addendum to the main Getting Started guide for those using Visual Studio on Windows. @@ -285,6 +290,9 @@ For API clients and LLVM developers. :doc:`DebuggingJITedCode` How to debug JITed code with GDB. +:doc:`MCJITDesignAndImplementation` + Describes the inner workings of MCJIT execution engine. + :doc:`BranchWeightMetadata` Provides information about Branch Prediction Information. @@ -315,6 +323,7 @@ Information about LLVM's development process. LLVMBuild HowToReleaseLLVM Packaging + ReleaseProcess :doc:`DeveloperPolicy` The LLVM project's policy towards developers and their contributions. @@ -335,6 +344,9 @@ Information about LLVM's development process. :doc:`HowToReleaseLLVM` This is a guide to preparing LLVM releases. Most developers can ignore it. +:doc:`ReleaseProcess` + This is a validate a new release, during the release process. Most developers can ignore it. + :doc:`Packaging` Advice on packaging LLVM into a distribution. diff --git a/docs/tutorial/LangImpl2.rst b/docs/tutorial/LangImpl2.rst index 7262afa8f3745..06b18ff6c2396 100644 --- a/docs/tutorial/LangImpl2.rst +++ b/docs/tutorial/LangImpl2.rst @@ -691,406 +691,8 @@ libraries, of course.) To build this, just compile with: Here is the code: -.. code-block:: c++ - - #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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter2/toy.cpp + :language: c++ `Next: Implementing Code Generation to LLVM IR `_ diff --git a/docs/tutorial/LangImpl3.rst b/docs/tutorial/LangImpl3.rst index 9d5f90839edc0..7174c09c622bb 100644 --- a/docs/tutorial/LangImpl3.rst +++ b/docs/tutorial/LangImpl3.rst @@ -587,574 +587,8 @@ our makefile/command line about which options to use: Here is the code: -.. code-block:: c++ - - // To build this: - // See example below. - - #include "llvm/DerivedTypes.h" - #include "llvm/IRBuilder.h" - #include "llvm/LLVMContext.h" - #include "llvm/Module.h" - #include "llvm/Analysis/Verifier.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, "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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter3/toy.cpp + :language: c++ `Next: Adding JIT and Optimizer Support `_ diff --git a/docs/tutorial/LangImpl4.rst b/docs/tutorial/LangImpl4.rst index 96c06d124ef1a..44e0cc150954c 100644 --- a/docs/tutorial/LangImpl4.rst +++ b/docs/tutorial/LangImpl4.rst @@ -438,624 +438,8 @@ properly at runtime. Here is the code: -.. code-block:: c++ - - #include "llvm/DerivedTypes.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/ExecutionEngine/JIT.h" - #include "llvm/IRBuilder.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/DataLayout.h" - #include "llvm/Transforms/Scalar.h" - #include "llvm/Support/TargetSelect.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, "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()) { - fprintf(stderr, "Read top-level expression:"); - LF->dump(); - - // 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 DataLayout(*TheExecutionEngine->getDataLayout())); - // 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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter4/toy.cpp + :language: c++ `Next: Extending the language: control flow `_ diff --git a/docs/tutorial/LangImpl5.rst b/docs/tutorial/LangImpl5.rst index 80d5f37bc4cd8..ed5b652f63384 100644 --- a/docs/tutorial/LangImpl5.rst +++ b/docs/tutorial/LangImpl5.rst @@ -742,866 +742,8 @@ the if/then/else and for expressions.. To build this example, use: Here is the code: -.. code-block:: c++ - - #include "llvm/DerivedTypes.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/ExecutionEngine/JIT.h" - #include "llvm/IRBuilder.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/DataLayout.h" - #include "llvm/Transforms/Scalar.h" - #include "llvm/Support/TargetSelect.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, "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()), 2, - "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()), 2, 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 DataLayout(*TheExecutionEngine->getDataLayout())); - // 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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter5/toy.cpp + :language: c++ `Next: Extending the language: user-defined operators `_ diff --git a/docs/tutorial/LangImpl6.rst b/docs/tutorial/LangImpl6.rst index a5a60bffe04a5..42839fbd75041 100644 --- a/docs/tutorial/LangImpl6.rst +++ b/docs/tutorial/LangImpl6.rst @@ -742,984 +742,8 @@ will cause problems on Windows. Here is the code: -.. code-block:: c++ - - #include "llvm/DerivedTypes.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/ExecutionEngine/JIT.h" - #include "llvm/IRBuilder.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/DataLayout.h" - #include "llvm/Transforms/Scalar.h" - #include "llvm/Support/TargetSelect.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[2] = { L, R }; - return Builder.CreateCall(F, Ops, "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, "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()), 2, - "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()), 2, 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 DataLayout(*TheExecutionEngine->getDataLayout())); - // 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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter6/toy.cpp + :language: c++ `Next: Extending the language: mutable variables / SSA construction `_ diff --git a/docs/tutorial/LangImpl7.rst b/docs/tutorial/LangImpl7.rst index 6dde2fe41d1ae..a2e47b5f8a267 100644 --- a/docs/tutorial/LangImpl7.rst +++ b/docs/tutorial/LangImpl7.rst @@ -853,1151 +853,8 @@ mutable variables and var/in support. To build this example, use: Here is the code: -.. code-block:: c++ - - #include "llvm/DerivedTypes.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/ExecutionEngine/JIT.h" - #include "llvm/IRBuilder.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/DataLayout.h" - #include "llvm/Transforms/Scalar.h" - #include "llvm/Support/TargetSelect.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 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(); - - 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[2] = { L, R }; - return Builder.CreateCall(F, Ops, "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, "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()), 2, - "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 DataLayout(*TheExecutionEngine->getDataLayout())); - // 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; - } +.. literalinclude:: ../../examples/Kaleidoscope/Chapter7/toy.cpp + :language: c++ `Next: Conclusion and other useful LLVM tidbits `_ diff --git a/docs/tutorial/OCamlLangImpl2.rst b/docs/tutorial/OCamlLangImpl2.rst index 83a22ab22d4f4..905b306746f1f 100644 --- a/docs/tutorial/OCamlLangImpl2.rst +++ b/docs/tutorial/OCamlLangImpl2.rst @@ -339,6 +339,9 @@ expression: (* 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 diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst index 69a9aee0962a5..dde53badd3ad8 100644 --- a/docs/tutorial/index.rst +++ b/docs/tutorial/index.rst @@ -34,7 +34,7 @@ External Tutorials A simple guide for how to implement an LLVM integrated assembler for an architecture. -.. _`Howto: Implementing LLVM Integrated Assembler`: http://www.embecosm.com/download/ean10.html +.. _`Howto: Implementing LLVM Integrated Assembler`: http://www.embecosm.com/appnotes/ean10/ean10-howto-llvmas-1.0.html Advanced Topics =============== diff --git a/docs/yaml2obj.rst b/docs/yaml2obj.rst index b269806e06f63..2c55f02f0dd7a 100644 --- a/docs/yaml2obj.rst +++ b/docs/yaml2obj.rst @@ -38,7 +38,7 @@ Here's a sample COFF file. ComplexType: IMAGE_SYM_DTYPE_NULL # (0) StorageClass: IMAGE_SYM_CLASS_STATIC # (3) NumberOfAuxSymbols: 1 - AuxillaryData: + AuxiliaryData: "\x24\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00" # |$.................| - Name: _main diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp index cd6eabfdffaa5..a6a109d527631 100644 --- a/examples/BrainF/BrainFDriver.cpp +++ b/examples/BrainF/BrainFDriver.cpp @@ -108,7 +108,7 @@ int main(int argc, char **argv) { if (OutputFilename != "-") { std::string ErrInfo; out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo, - raw_fd_ostream::F_Binary); + sys::fs::F_Binary); } } diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index f9498a5fbfb3b..d6954e83be4b4 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -339,7 +339,7 @@ void deleteOurException(OurUnwindException *expToDelete) { /// 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://mentorembedded.github.com/cxx-abi/abi-eh.html +/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html /// @unlink /// @param expToDelete exception instance to delete void deleteFromUnwindOurException(_Unwind_Reason_Code reason, @@ -1562,7 +1562,7 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module, return(outerCatchFunct); } - +namespace { /// Represents our foreign exceptions class OurCppRunException : public std::runtime_error { public: @@ -1577,9 +1577,9 @@ public: std::runtime_error::operator=(toCopy))); } - ~OurCppRunException (void) throw () {} + virtual ~OurCppRunException (void) throw () {} }; - +} // end anonymous namespace /// Throws foreign C++ exception. /// @param ignoreIt unused parameter that allows function to match implied @@ -1950,7 +1950,6 @@ int main(int argc, char *argv[]) { // If not set, exception handling will not be turned on llvm::TargetOptions Opts; - Opts.JITExceptionHandling = true; llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); @@ -1960,14 +1959,14 @@ int main(int argc, char *argv[]) { // Make the module, which holds all the code. llvm::Module *module = new llvm::Module("my cool jit", context); - llvm::JITMemoryManager *MemMgr = new llvm::SectionMemoryManager(); + llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); // Build engine with JIT llvm::EngineBuilder factory(module); factory.setEngineKind(llvm::EngineKind::JIT); factory.setAllocateGVsWithCode(false); factory.setTargetOptions(Opts); - factory.setJITMemoryManager(MemMgr); + factory.setMCJITMemoryManager(MemMgr); factory.setUseMCJIT(true); llvm::ExecutionEngine *executionEngine = factory.create(); diff --git a/examples/ExceptionDemo/Makefile b/examples/ExceptionDemo/Makefile index 480744730eb79..58d9def0b7eea 100644 --- a/examples/ExceptionDemo/Makefile +++ b/examples/ExceptionDemo/Makefile @@ -11,6 +11,6 @@ TOOLNAME = ExceptionDemo EXAMPLE_TOOL = 1 REQUIRES_EH = 1 -LINK_COMPONENTS := jit interpreter nativecodegen +LINK_COMPONENTS := jit mcjit nativecodegen include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter2/toy.cpp b/examples/Kaleidoscope/Chapter2/toy.cpp index 1cf6caacb6af8..cd901394a524e 100644 --- a/examples/Kaleidoscope/Chapter2/toy.cpp +++ b/examples/Kaleidoscope/Chapter2/toy.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -74,7 +75,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -83,9 +84,8 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { - double Val; public: - NumberExprAST(double val) : Val(val) {} + NumberExprAST(double val) {} }; /// VariableExprAST - Expression class for referencing a variable, like "a". @@ -97,11 +97,8 @@ public: /// 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) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) {} }; /// CallExprAST - Expression class for function calls. @@ -127,13 +124,10 @@ public: /// FunctionAST - This class represents a function definition itself. class FunctionAST { - PrototypeAST *Proto; - ExprAST *Body; public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) {} }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser @@ -165,7 +159,6 @@ static int GetTokPrecedence() { /// 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(); diff --git a/examples/Kaleidoscope/Chapter3/toy.cpp b/examples/Kaleidoscope/Chapter3/toy.cpp index 48cfbe6decb24..a7b60ba3220a4 100644 --- a/examples/Kaleidoscope/Chapter3/toy.cpp +++ b/examples/Kaleidoscope/Chapter3/toy.cpp @@ -3,6 +3,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include #include #include #include @@ -79,7 +80,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -146,6 +147,7 @@ public: Function *Codegen(); }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index 971a7c68b217d..27c3f4f22d67d 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -10,6 +10,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" +#include #include #include #include @@ -86,7 +87,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -153,6 +154,7 @@ public: Function *Codegen(); }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index 5558d08e1d0c4..fe4cdfe757450 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -10,6 +10,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" +#include #include #include #include @@ -95,7 +96,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -182,6 +183,7 @@ public: Function *Codegen(); }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index 52926eb99f17c..b7b347db0d877 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -10,6 +10,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" +#include #include #include #include @@ -100,7 +101,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -210,6 +211,7 @@ public: Function *Codegen(); }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index ba192d6243cde..5c66f5c83722a 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -10,6 +10,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" +#include #include #include #include @@ -104,7 +105,7 @@ static int gettok() { //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// - +namespace { /// ExprAST - Base class for all expression nodes. class ExprAST { public: @@ -228,6 +229,7 @@ public: Function *Codegen(); }; +} // end anonymous namespace //===----------------------------------------------------------------------===// // Parser diff --git a/examples/Kaleidoscope/MCJIT/README.txt b/examples/Kaleidoscope/MCJIT/README.txt new file mode 100644 index 0000000000000..ba742645acc11 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/README.txt @@ -0,0 +1,12 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany a series of blog posts +that describe the process of porting the Kaleidoscope tutorial to use the MCJIT +execution engine instead of the older JIT engine. + +When the blog posts are ready this file will be updated with links to the posts. + +These directories contain Makefiles that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/cached/Makefile b/examples/Kaleidoscope/MCJIT/cached/Makefile new file mode 100644 index 0000000000000..dde39a75d7675 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/Makefile @@ -0,0 +1,11 @@ +all: toy-mcjit toy-jit toy-ir-gen + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native irreader` -o toy-mcjit + +toy-jit : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-jit + +# This is a special build for the purpose of converting Kaleidoscope input to an IR file +toy-ir-gen : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic -fno-rtti -DDUMP_FINAL_MODULE `llvm-config --cppflags --ldflags --libs core jit native irreader` -o toy-ir-gen diff --git a/examples/Kaleidoscope/MCJIT/cached/README.txt b/examples/Kaleidoscope/MCJIT/cached/README.txt new file mode 100644 index 0000000000000..6acaf057f286b --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/README.txt @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the third version of the +program, now modified to accept an input IR file on the command line and, +optionally, to use a basic caching mechanism to store generated object images. + +The toy-jit.cpp file contains a version of the original JIT-based source code +that has been modified to support the input IR file command line option. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. Another Python script will split generated input files into +definitions and function calls for the purpose of testing the IR input and +caching facilities. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/cached/genk-timing.py b/examples/Kaleidoscope/MCJIT/cached/genk-timing.py new file mode 100644 index 0000000000000..96dd6db5da3df --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/genk-timing.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/cached/split-lib.py b/examples/Kaleidoscope/MCJIT/cached/split-lib.py new file mode 100644 index 0000000000000..5cdcc6d46c049 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/split-lib.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.shfile = open(scriptname, 'w') + self.timeFile = outputname + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, irname, callname): + """Echo some comments and invoke both versions of toy""" + rootname = irname + if '.' in irname: + rootname = irname[:irname.rfind('.')] + self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class LibScriptGenerator: + """Used to generate a bash script which will convert Kaleidoscope files to IR""" + def __init__(self, filename): + self.shfile = open(filename, 'w') + + def writeLibGenCall(self, libname, irname): + self.shfile.write("./toy-ir-gen < %s 2> %s\n" % (libname, irname)) + +def splitScript(inputname, libGenScript, timingScript): + rootname = inputname[:-2] + libname = rootname + "-lib.k" + irname = rootname + "-lib.ir" + callname = rootname + "-call.k" + infile = open(inputname, "r") + libfile = open(libname, "w") + callfile = open(callname, "w") + print "Splitting %s into %s and %s" % (inputname, callname, libname) + for line in infile: + if not line.startswith("#"): + if line.startswith("print"): + callfile.write(line) + else: + libfile.write(line) + libGenScript.writeLibGenCall(libname, irname) + timingScript.writeTimingCall(irname, callname) + +# Execution begins here +libGenScript = LibScriptGenerator("make-libs.sh") +timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt") + +script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k", + "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k", + "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"] + +for script in script_list: + splitScript(script, libGenScript, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp new file mode 100644 index 0000000000000..784781bd9f459 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -0,0 +1,1208 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +namespace { + cl::opt + InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); +} // namespace + +//===----------------------------------------------------------------------===// +// 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 FunctionPassManager *TheFPM; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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; +#ifdef USE_MCJIT + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); +#else + Function *F = TheModule->getFunction(std::string("unary")+Opcode); +#endif + 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. + // For now, I'm building without RTTI because LLVM builds that way by + // default and so we need to build that way to use the command line supprt. + // If you build LLVM with RTTI this can be changed back to a dynamic_cast. + VariableExprAST *LHSE = reinterpret_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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // 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, "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()), 2, + "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()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } 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; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Command line input file handlers +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + return M; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Make the module, which holds all the code. + if (!InputIR.empty()) { + TheModule = parseInputIR(InputIR); + } else { + 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 DataLayout(*TheExecutionEngine->getDataLayout())); + // 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; + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheFPM = 0; +#if !defined(MINIMAL_STDERR_OUTPUT) || defined(DUMP_FINAL_MODULE) + TheModule->dump(); +#endif + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp new file mode 100644 index 0000000000000..5bc49d7dbc1bd --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -0,0 +1,1552 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +cl::opt +InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); + +cl::opt +UseObjectCache("use-object-cache", + cl::desc("Enable use of the MCJIT object caching"), + cl::init(false)); + +//===----------------------------------------------------------------------===// +// 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(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT object cache class +//===----------------------------------------------------------------------===// + +class MCJITObjectCache : public ObjectCache { +public: + MCJITObjectCache() { + // Set IR cache directory + sys::fs::current_path(CacheDir); + sys::path::append(CacheDir, "toy_object_cache"); + } + + virtual ~MCJITObjectCache() { + } + + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128>IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(CacheDir.str()) && sys::fs::create_directory(CacheDir.str())) { + fprintf(stderr, "Unable to create cache directory\n"); + return; + } + std::string ErrStr; + raw_fd_ostream IRObjectFile(IRCacheFile.c_str(), ErrStr, raw_fd_ostream::F_Binary); + IRObjectFile << Obj->getBuffer(); + } + } + + // MCJIT will call this function before compiling any module + // MCJIT takes ownership of both the MemoryBuffer object and the memory + // to which it refers. + virtual MemoryBuffer* getObject(const Module* M) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128> IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(IRCacheFile.str())) { + // This file isn't in our cache + return NULL; + } + OwningPtr IRObjectBuffer; + MemoryBuffer::getFile(IRCacheFile.c_str(), IRObjectBuffer, -1, false); + // MCJIT will want to write into this buffer, and we don't want that + // because the file has probably just been mmapped. Instead we make + // a copy. The filed-based buffer will be released when it goes + // out of scope. + return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer()); + } + + return NULL; + } + +private: + SmallString<128> CacheDir; +}; + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + ExecutionEngine *compileModule(Module *M); + void closeCurrentModule(); + void addModule(Module *M); + void dump(); + +private: + typedef std::vector ModuleVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + std::map EngineMap; + MCJITObjectCache OurObjectCache; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + OpenModule = NULL; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + if (M == OpenModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + if (UseObjectCache) + NewEngine->setObjectCache(&OurObjectCache); + + // Get the ModuleID so we can identify IR input files + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, it doesn't need function passes run. + if (0 != ModuleID.compare(0, 3, "IR:")) { + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + } + + // Store this engine + EngineMap[M] = NewEngine; + NewEngine->finalizeObject(); + + return NewEngine; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::addModule(Module* M) { + Modules.push_back(M); +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(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 = reinterpret_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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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 = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->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, "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()), 2, + "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); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->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); + + 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 void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + TheHelper->closeCurrentModule(); + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } 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 = TheHelper->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; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Command line input file handler +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, getGlobalContext()); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + char ModID[256]; + sprintf(ModID, "IR:%s", InputFile.c_str()); + M->setModuleIdentifier(ModID); + + TheHelper->addModule(M); + return M; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + if (!InputIR.empty()) { + parseInputIR(InputIR); + } + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/complete/Makefile b/examples/Kaleidoscope/MCJIT/complete/Makefile new file mode 100644 index 0000000000000..9e45d17a69f01 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/Makefile @@ -0,0 +1,4 @@ +all: toy + +toy : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core jit mcjit native irreader` -o toy diff --git a/examples/Kaleidoscope/MCJIT/complete/README.txt b/examples/Kaleidoscope/MCJIT/complete/README.txt new file mode 100644 index 0000000000000..82bc397a4eb91 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/README.txt @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory combines all previous versions, including the +old JIT-based implementation, into a single file for easy comparison with +command line options to select between the various possibilities. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. Another Python script will split generated input files into +definitions and function calls for the purpose of testing the IR input and +caching facilities. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/complete/genk-timing.py b/examples/Kaleidoscope/MCJIT/complete/genk-timing.py new file mode 100644 index 0000000000000..72591fe8bd499 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/genk-timing.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT (original)\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=false < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT (lazy)\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true < %s > %s-mcjit-lazy.out 2> %s-mcjit-lazy.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=false < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/complete/split-lib.py b/examples/Kaleidoscope/MCJIT/complete/split-lib.py new file mode 100644 index 0000000000000..f6bec0276d858 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/split-lib.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.shfile = open(scriptname, 'w') + self.timeFile = outputname + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, irname, callname): + """Echo some comments and invoke both versions of toy""" + rootname = irname + if '.' in irname: + rootname = irname[:irname.rfind('.')] + self.shfile.write("echo \"%s: Calls %s\" >> %s\n" % (callname, irname, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT again\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true -use-object-cache -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy -suppress-prompts -use-mcjit=false -input-IR=%s < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (irname, callname, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class LibScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, filename): + self.shfile = open(filename, 'w') + + def writeLibGenCall(self, libname, irname): + self.shfile.write("./toy -suppress-prompts -use-mcjit=false -dump-modules < %s 2> %s\n" % (libname, irname)) + +def splitScript(inputname, libGenScript, timingScript): + rootname = inputname[:-2] + libname = rootname + "-lib.k" + irname = rootname + "-lib.ir" + callname = rootname + "-call.k" + infile = open(inputname, "r") + libfile = open(libname, "w") + callfile = open(callname, "w") + print "Splitting %s into %s and %s" % (inputname, callname, libname) + for line in infile: + if not line.startswith("#"): + if line.startswith("print"): + callfile.write(line) + else: + libfile.write(line) + libGenScript.writeLibGenCall(libname, irname) + timingScript.writeTimingCall(irname, callname) + +# Execution begins here +libGenScript = LibScriptGenerator("make-libs.sh") +timingScript = TimingScriptGenerator("time-lib.sh", "lib-timing.txt") + +script_list = ["test-5000-3-50-50.k", "test-5000-10-100-10.k", "test-5000-10-5-10.k", "test-5000-10-1-0.k", + "test-1000-3-10-50.k", "test-1000-10-100-10.k", "test-1000-10-5-10.k", "test-1000-10-1-0.k", + "test-200-3-2-50.k", "test-200-10-40-10.k", "test-200-10-2-10.k", "test-200-10-1-0.k"] + +for script in script_list: + splitScript(script, libGenScript, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp new file mode 100644 index 0000000000000..1f804d565655e --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -0,0 +1,1711 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Command-line options +//===----------------------------------------------------------------------===// + +namespace { + cl::opt + InputIR("input-IR", + cl::desc("Specify the name of an IR file to load for function definitions"), + cl::value_desc("input IR file name")); + + cl::opt + VerboseOutput("verbose", + cl::desc("Enable verbose output (results, IR, etc.) to stderr"), + cl::init(false)); + + cl::opt + SuppressPrompts("suppress-prompts", + cl::desc("Disable printing the 'ready' prompt"), + cl::init(false)); + + cl::opt + DumpModulesOnExit("dump-modules", + cl::desc("Dump IR from modules to stderr on shutdown"), + cl::init(false)); + + cl::opt UseMCJIT( + "use-mcjit", cl::desc("Use the MCJIT execution engine"), + cl::init(true)); + + cl::opt EnableLazyCompilation( + "enable-lazy-compilation", cl::desc("Enable lazy compilation when using the MCJIT engine"), + cl::init(true)); + + cl::opt UseObjectCache( + "use-object-cache", cl::desc("Enable use of the MCJIT object caching"), + cl::init(false)); +} // namespace + +//===----------------------------------------------------------------------===// +// 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(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT object cache class +//===----------------------------------------------------------------------===// + +class MCJITObjectCache : public ObjectCache { +public: + MCJITObjectCache() { + // Set IR cache directory + sys::fs::current_path(CacheDir); + sys::path::append(CacheDir, "toy_object_cache"); + } + + virtual ~MCJITObjectCache() { + } + + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128>IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(CacheDir.str()) && sys::fs::create_directory(CacheDir.str())) { + fprintf(stderr, "Unable to create cache directory\n"); + return; + } + std::string ErrStr; + raw_fd_ostream IRObjectFile(IRCacheFile.c_str(), ErrStr, raw_fd_ostream::F_Binary); + IRObjectFile << Obj->getBuffer(); + } + } + + // MCJIT will call this function before compiling any module + // MCJIT takes ownership of both the MemoryBuffer object and the memory + // to which it refers. + virtual MemoryBuffer* getObject(const Module* M) { + // Get the ModuleID + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, cache it + if (0 == ModuleID.compare(0, 3, "IR:")) { + std::string IRFileName = ModuleID.substr(3); + SmallString<128> IRCacheFile = CacheDir; + sys::path::append(IRCacheFile, IRFileName); + if (!sys::fs::exists(IRCacheFile.str())) { + // This file isn't in our cache + return NULL; + } + OwningPtr IRObjectBuffer; + MemoryBuffer::getFile(IRCacheFile.c_str(), IRObjectBuffer, -1, false); + // MCJIT will want to write into this buffer, and we don't want that + // because the file has probably just been mmapped. Instead we make + // a copy. The filed-based buffer will be released when it goes + // out of scope. + return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer()); + } + + return NULL; + } + +private: + SmallString<128> CacheDir; +}; + +//===----------------------------------------------------------------------===// +// IR input file handler +//===----------------------------------------------------------------------===// + +Module* parseInputIR(std::string InputFile, LLVMContext &Context) { + SMDiagnostic Err; + Module *M = ParseIRFile(InputFile, Err, Context); + if (!M) { + Err.print("IR parsing failed: ", errs()); + return NULL; + } + + char ModID[256]; + sprintf(ModID, "IR:%s", InputFile.c_str()); + M->setModuleIdentifier(ModID); + return M; +} + +//===----------------------------------------------------------------------===// +// Helper class for execution engine abstraction +//===----------------------------------------------------------------------===// + +class BaseHelper +{ +public: + BaseHelper() {} + virtual ~BaseHelper() {} + + virtual Function *getFunction(const std::string FnName) = 0; + virtual Module *getModuleForNewFunction() = 0; + virtual void *getPointerToFunction(Function* F) = 0; + virtual void *getPointerToNamedFunction(const std::string &Name) = 0; + virtual void closeCurrentModule() = 0; + virtual void runFPM(Function &F) = 0; + virtual void dump(); +}; + +//===----------------------------------------------------------------------===// +// Helper class for JIT execution engine +//===----------------------------------------------------------------------===// + +class JITHelper : public BaseHelper { +public: + JITHelper(LLVMContext &Context) { + // Make the module, which holds all the code. + if (!InputIR.empty()) { + TheModule = parseInputIR(InputIR, Context); + } else { + 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); + } + + TheFPM = new FunctionPassManager(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + TheFPM->add(new DataLayout(*TheExecutionEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + TheFPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + TheFPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + TheFPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + TheFPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + TheFPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + TheFPM->add(createCFGSimplificationPass()); + + TheFPM->doInitialization(); + } + + virtual ~JITHelper() { + if (TheFPM) + delete TheFPM; + if (TheExecutionEngine) + delete TheExecutionEngine; + } + + virtual Function *getFunction(const std::string FnName) { + assert(TheModule); + return TheModule->getFunction(FnName); + } + + virtual Module *getModuleForNewFunction() { + assert(TheModule); + return TheModule; + } + + virtual void *getPointerToFunction(Function* F) { + assert(TheExecutionEngine); + return TheExecutionEngine->getPointerToFunction(F); + } + + virtual void *getPointerToNamedFunction(const std::string &Name) { + return TheExecutionEngine->getPointerToNamedFunction(Name); + } + + virtual void runFPM(Function &F) { + assert(TheFPM); + TheFPM->run(F); + } + + virtual void closeCurrentModule() { + // This should never be called for JIT + assert(false); + } + + virtual void dump() { + assert(TheModule); + TheModule->dump(); + } + +private: + Module *TheModule; + ExecutionEngine *TheExecutionEngine; + FunctionPassManager *TheFPM; +}; + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper : public BaseHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), CurrentModule(NULL) { + if (!InputIR.empty()) { + Module *M = parseInputIR(InputIR, Context); + Modules.push_back(M); + if (!EnableLazyCompilation) + compileModule(M); + } + } + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + void closeCurrentModule(); + virtual void runFPM(Function &F) {} // Not needed, see compileModule + void dump(); + +protected: + ExecutionEngine *compileModule(Module *M); + +private: + typedef std::vector ModuleVector; + + MCJITObjectCache OurObjectCache; + + LLVMContext &Context; + ModuleVector Modules; + + std::map EngineMap; + + Module *CurrentModule; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = RTDyldMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == CurrentModule) + return F; + + assert(CurrentModule != NULL); + + // This function is in a module that has already been JITed. + // We just need a prototype for external linkage. + Function *PF = CurrentModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + CurrentModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (CurrentModule) + return CurrentModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + CurrentModule = M; + + return M; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + assert(EngineMap.find(M) == EngineMap.end()); + + if (M == CurrentModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *EE = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!EE) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + if (UseObjectCache) + EE->setObjectCache(&OurObjectCache); + // Get the ModuleID so we can identify IR input files + const std::string ModuleID = M->getModuleIdentifier(); + + // If we've flagged this as an IR file, it doesn't need function passes run. + if (0 != ModuleID.compare(0, 3, "IR:")) { + FunctionPassManager *FPM = 0; + + // Create a FPM for this module + FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*EE->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + delete FPM; + } + + EE->finalizeObject(); + + // Store this engine + EngineMap[M] = EE; + + return EE; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + // If we have an open module (and we should), pack it up + if (CurrentModule) { + CurrentModule = NULL; + } +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static BaseHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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; + if (UseMCJIT) + F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); + else + F = TheHelper->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. + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = reinterpret_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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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; + if (UseMCJIT) + F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + else + F = TheHelper->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // 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, "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()), 2, + "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); + + std::string FnName; + if (UseMCJIT) + FnName = MakeLegalFunctionName(Name); + else + FnName = Name; + + Module* M = TheHelper->getModuleForNewFunction(); + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // FIXME: Implement duplicate function detection. + // The check below will only work if the duplicate is in the open module. + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->getFunction(FnName); + // 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. + if (!UseMCJIT) + TheHelper->runFPM(*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 void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (UseMCJIT && EnableLazyCompilation) + TheHelper->closeCurrentModule(); + Function *LF = F->Codegen(); + if (LF && VerboseOutput) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + Function *F = P->Codegen(); + if (F && VerboseOutput) { + 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 = TheHelper->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; + double Result = FP(); + if (VerboseOutput) + fprintf(stderr, "Evaluated to %f\n", Result); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + if (!SuppressPrompts) + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + if (UseMCJIT) { + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + } + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "Kaleidoscope example program\n"); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Make the Helper, which holds all the code. + if (UseMCJIT) + TheHelper = new MCJITHelper(Context); + else + TheHelper = new JITHelper(Context); + + // Prime the first token. + if (!SuppressPrompts) + fprintf(stderr, "ready> "); + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + if (DumpModulesOnExit) + TheHelper->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/initial/Makefile b/examples/Kaleidoscope/MCJIT/initial/Makefile new file mode 100644 index 0000000000000..2989832d3c796 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/Makefile @@ -0,0 +1,4 @@ +all: toy-mcjit + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit diff --git a/examples/Kaleidoscope/MCJIT/initial/README.txt b/examples/Kaleidoscope/MCJIT/initial/README.txt new file mode 100644 index 0000000000000..b352a784522f3 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/README.txt @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the initial working version of +the program before subsequent performance improvements are applied. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required, as mentioned in the blog posts. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp new file mode 100644 index 0000000000000..7e2f7df0b1ed3 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -0,0 +1,1382 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#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(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + void dump(); + +private: + typedef std::vector ModuleVector; + typedef std::vector EngineVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + EngineVector Engines; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + if (OpenModule) + delete OpenModule; + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) + delete *it; +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // See if an existing instance of MCJIT has this function. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + void *P = (*it)->getPointerToFunction(F); + if (P) + return P; + } + + // If we didn't find the function, see if we can generate it. + if (OpenModule) { + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(OpenModule) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(OpenModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = OpenModule->end(); + for (it = OpenModule->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + + OpenModule = NULL; + Engines.push_back(NewEngine); + NewEngine->finalizeObject(); + return NewEngine->getPointerToFunction(F); + } + return NULL; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the function in each of our execution engines. + EngineVector::iterator begin = Engines.begin(); + EngineVector::iterator end = Engines.end(); + EngineVector::iterator it; + for (it = begin; it != end; ++it) { + if (Function *F = (*it)->FindFunctionNamed(Name.c_str())) + return (*it)->getPointerToFunction(F); + } + + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(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 = reinterpret_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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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 = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->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, "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()), 2, + "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); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->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); + + 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 void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } 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 = TheHelper->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; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/lazy/Makefile b/examples/Kaleidoscope/MCJIT/lazy/Makefile new file mode 100644 index 0000000000000..21cbc18d6e24f --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/Makefile @@ -0,0 +1,7 @@ +all: toy-mcjit toy-jit + +toy-mcjit : toy.cpp + clang++ toy.cpp -g -O3 -rdynamic -fno-rtti `llvm-config --cppflags --ldflags --libs core mcjit native` -o toy-mcjit + +toy-jit : toy-jit.cpp + clang++ toy-jit.cpp -g -O3 -rdynamic `llvm-config --cppflags --ldflags --libs core jit native` -o toy-jit diff --git a/examples/Kaleidoscope/MCJIT/lazy/README.txt b/examples/Kaleidoscope/MCJIT/lazy/README.txt new file mode 100644 index 0000000000000..c5c271e02f697 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/README.txt @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with MCJIT +//===----------------------------------------------------------------------===// + +The files in this directory are meant to accompany the first in a series of +three blog posts that describe the process of porting the Kaleidoscope tutorial +to use the MCJIT execution engine instead of the older JIT engine. + +When the blog post is ready this file will be updated with a link to the post. + +The source code in this directory demonstrates the second version of the +program, now modified to implement a sort of 'lazy' compilation. + +The toy-jit.cpp file contains a version of the original JIT-based source code +that has been modified to disable most stderr output for timing purposes. + +This directory contain a Makefile that allow the code to be built in a +standalone manner, independent of the larger LLVM build infrastructure. To build +the program you will need to have 'clang++' and 'llvm-config' in your path. If +you attempt to build using the LLVM 3.3 release, some minor modifications will +be required. + +This directory also contains a Python script that may be used to generate random +input for the program and test scripts to capture data for rough performance +comparisons. \ No newline at end of file diff --git a/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py b/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py new file mode 100644 index 0000000000000..96dd6db5da3df --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/genk-timing.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +import sys +import random + +class TimingScriptGenerator: + """Used to generate a bash script which will invoke the toy and time it""" + def __init__(self, scriptname, outputname): + self.timeFile = outputname + self.shfile = open(scriptname, 'w') + self.shfile.write("echo \"\" > %s\n" % self.timeFile) + + def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls): + """Echo some comments and invoke both versions of toy""" + rootname = filename + if '.' in filename: + rootname = filename[:filename.rfind('.')] + self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With MCJIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-mcjit < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile) + self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"") + self.shfile.write(" -o %s -a " % self.timeFile) + self.shfile.write("./toy-jit < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname)) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + self.shfile.write("echo \"\" >> %s\n" % self.timeFile) + +class KScriptGenerator: + """Used to generate random Kaleidoscope code""" + def __init__(self, filename): + self.kfile = open(filename, 'w') + self.nextFuncNum = 1 + self.lastFuncNum = None + self.callWeighting = 0.1 + # A mapping of calls within functions with no duplicates + self.calledFunctionTable = {} + # A list of function calls which will actually be executed + self.calledFunctions = [] + # A comprehensive mapping of calls within functions + # used for computing the total number of calls + self.comprehensiveCalledFunctionTable = {} + self.totalCallsExecuted = 0 + + def updateTotalCallCount(self, callee): + # Count this call + self.totalCallsExecuted += 1 + # Then count all the functions it calls + if callee in self.comprehensiveCalledFunctionTable: + for child in self.comprehensiveCalledFunctionTable[callee]: + self.updateTotalCallCount(child) + + def updateFunctionCallMap(self, caller, callee): + """Maintains a map of functions that are called from other functions""" + if not caller in self.calledFunctionTable: + self.calledFunctionTable[caller] = [] + if not callee in self.calledFunctionTable[caller]: + self.calledFunctionTable[caller].append(callee) + if not caller in self.comprehensiveCalledFunctionTable: + self.comprehensiveCalledFunctionTable[caller] = [] + self.comprehensiveCalledFunctionTable[caller].append(callee) + + def updateCalledFunctionList(self, callee): + """Maintains a list of functions that will actually be called""" + # Update the total call count + self.updateTotalCallCount(callee) + # If this function is already in the list, don't do anything else + if callee in self.calledFunctions: + return + # Add this function to the list of those that will be called. + self.calledFunctions.append(callee) + # If this function calls other functions, add them too + if callee in self.calledFunctionTable: + for subCallee in self.calledFunctionTable[callee]: + self.updateCalledFunctionList(subCallee) + + def setCallWeighting(self, weight): + """ Sets the probably of generating a function call""" + self.callWeighting = weight + + def writeln(self, line): + self.kfile.write(line + '\n') + + def writeComment(self, comment): + self.writeln('# ' + comment) + + def writeEmptyLine(self): + self.writeln("") + + def writePredefinedFunctions(self): + self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands") + self.writeComment("and just returns the RHS.") + self.writeln("def binary : 1 (x y) y;") + self.writeEmptyLine() + self.writeComment("Helper functions defined within toy") + self.writeln("extern putchard(x);") + self.writeln("extern printd(d);") + self.writeln("extern printlf();") + self.writeEmptyLine() + self.writeComment("Print the result of a function call") + self.writeln("def printresult(N Result)") + self.writeln(" # 'result('") + self.writeln(" putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :") + self.writeln(" printd(N) :"); + self.writeln(" # ') = '") + self.writeln(" putchard(41) : putchard(32) : putchard(61) : putchard(32) :") + self.writeln(" printd(Result) :"); + self.writeln(" printlf();") + self.writeEmptyLine() + + def writeRandomOperation(self, LValue, LHS, RHS): + shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting) + if shouldCallFunc: + funcToCall = random.randrange(1, self.lastFuncNum - 1) + self.updateFunctionCallMap(self.lastFuncNum, funcToCall) + self.writeln(" %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS)) + else: + possibleOperations = ["+", "-", "*", "/"] + operation = random.choice(possibleOperations) + if operation == "-": + # Don't let our intermediate value become zero + # This is complicated by the fact that '<' is our only comparison operator + self.writeln(" if %s < %s then" % (LHS, RHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else if %s < %s then" % (RHS, LHS)) + self.writeln(" %s = %s %s %s" % (LValue, LHS, operation, RHS)) + self.writeln(" else") + self.writeln(" %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100))) + else: + self.writeln(" %s = %s %s %s :" % (LValue, LHS, operation, RHS)) + + def getNextFuncNum(self): + result = self.nextFuncNum + self.nextFuncNum += 1 + self.lastFuncNum = result + return result + + def writeFunction(self, elements): + funcNum = self.getNextFuncNum() + self.writeComment("Auto-generated function number %d" % funcNum) + self.writeln("def func%d(X Y)" % funcNum) + self.writeln(" var temp1 = X,") + self.writeln(" temp2 = Y,") + self.writeln(" temp3 in") + # Initialize the variable names to be rotated + first = "temp3" + second = "temp1" + third = "temp2" + # Write some random operations + for i in range(elements): + self.writeRandomOperation(first, second, third) + # Rotate the variables + temp = first + first = second + second = third + third = temp + self.writeln(" " + third + ";") + self.writeEmptyLine() + + def writeFunctionCall(self): + self.writeComment("Call the last function") + arg1 = random.uniform(1, 100) + arg2 = random.uniform(1, 100) + self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2)) + self.writeEmptyLine() + self.updateCalledFunctionList(self.lastFuncNum) + + def writeFinalFunctionCounts(self): + self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum)) + +def generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript): + """ Generate a random Kaleidoscope script based on the given parameters """ + print "Generating " + filename + print(" %d functions, %d elements per function, %d functions between execution" % + (numFuncs, elementsPerFunc, funcsBetweenExec)) + print(" Call weighting = %f" % callWeighting) + script = KScriptGenerator(filename) + script.setCallWeighting(callWeighting) + script.writeComment("===========================================================================") + script.writeComment("Auto-generated script") + script.writeComment(" %d functions, %d elements per function, %d functions between execution" + % (numFuncs, elementsPerFunc, funcsBetweenExec)) + script.writeComment(" call weighting = %f" % callWeighting) + script.writeComment("===========================================================================") + script.writeEmptyLine() + script.writePredefinedFunctions() + funcsSinceLastExec = 0 + for i in range(numFuncs): + script.writeFunction(elementsPerFunc) + funcsSinceLastExec += 1 + if funcsSinceLastExec == funcsBetweenExec: + script.writeFunctionCall() + funcsSinceLastExec = 0 + # Always end with a function call + if funcsSinceLastExec > 0: + script.writeFunctionCall() + script.writeEmptyLine() + script.writeFinalFunctionCounts() + funcsCalled = len(script.calledFunctions) + print " Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted) + timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted) + +# Execution begins here +random.seed() + +timingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt") + +dataSets = [(5000, 3, 50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0), + (1000, 3, 10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0), + ( 200, 3, 2, 0.50), ( 200, 10, 40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)] + +# Generate the code +for (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets: + filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100)) + generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript) +print "All done!" diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp new file mode 100644 index 0000000000000..c3d88c838e090 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -0,0 +1,1168 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#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 FunctionPassManager *TheFPM; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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; +#ifdef USE_MCJIT + Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); +#else + Function *F = TheModule->getFunction(std::string("unary")+Opcode); +#endif + 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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) { + char error_str[64]; + sprintf(error_str, "Unknown function referenced %s", Callee.c_str()); + return ErrorV(error_str); + } + + // 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, "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()), 2, + "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()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } 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; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main(int argc, char **argv) { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // 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 DataLayout(*TheExecutionEngine->getDataLayout())); + // 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; + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheFPM = 0; +#ifndef MINIMAL_STDERR_OUTPUT + TheModule->dump(); +#endif + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp new file mode 100644 index 0000000000000..189331c083f98 --- /dev/null +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -0,0 +1,1423 @@ +#define MINIMAL_STDERR_OUTPUT + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#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(); +} + +//===----------------------------------------------------------------------===// +// Quick and dirty hack +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const char *root) +{ + static int i = 0; + char s[16]; + sprintf(s, "%s%d", root, i++); + std::string S = s; + return S; +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + if (!Name.length()) + return GenerateUniqueName("anon_func_"); + + // Start with what we have + NewName = Name; + + // Look for a numberic first character + if (NewName.find_first_of("0123456789") == 0) { + NewName.insert(0, 1, 'n'); + } + + // Replace illegal characters with their ASCII equivalent + std::string legal_elements = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t pos; + while ((pos = NewName.find_first_not_of(legal_elements)) != std::string::npos) { + char old_c = NewName.at(pos); + char new_str[16]; + sprintf(new_str, "%d", (int)old_c); + NewName = NewName.replace(pos, 1, new_str); + } + + return NewName; +} + +//===----------------------------------------------------------------------===// +// MCJIT helper class +//===----------------------------------------------------------------------===// + +class MCJITHelper +{ +public: + MCJITHelper(LLVMContext& C) : Context(C), OpenModule(NULL) {} + ~MCJITHelper(); + + Function *getFunction(const std::string FnName); + Module *getModuleForNewFunction(); + void *getPointerToFunction(Function* F); + void *getPointerToNamedFunction(const std::string &Name); + ExecutionEngine *compileModule(Module *M); + void closeCurrentModule(); + void dump(); + +private: + typedef std::vector ModuleVector; + + LLVMContext &Context; + Module *OpenModule; + ModuleVector Modules; + std::map EngineMap; +}; + +class HelpingMemoryManager : public SectionMemoryManager +{ + HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified function. + /// Our implementation will attempt to find functions in other + /// modules associated with the MCJITHelper to cross link functions + /// from one generated module to another. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); +private: + MCJITHelper *MasterHelper; +}; + +void *HelpingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) +{ + // Try the standard symbol resolution first, but ask it not to abort. + void *pfn = SectionMemoryManager::getPointerToNamedFunction(Name, false); + if (pfn) + return pfn; + + pfn = MasterHelper->getPointerToNamedFunction(Name); + if (!pfn && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return pfn; +} + +MCJITHelper::~MCJITHelper() +{ + // Walk the vector of modules. + ModuleVector::iterator it, end; + for (it = Modules.begin(), end = Modules.end(); + it != end; ++it) { + // See if we have an execution engine for this module. + std::map::iterator mapIt = EngineMap.find(*it); + // If we have an EE, the EE owns the module so just delete the EE. + if (mapIt != EngineMap.end()) { + delete mapIt->second; + } else { + // Otherwise, we still own the module. Delete it now. + delete *it; + } + } +} + +Function *MCJITHelper::getFunction(const std::string FnName) { + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(FnName); + if (F) { + if (*it == OpenModule) + return F; + + assert(OpenModule != NULL); + + // This function is in a module that has already been JITed. + // We need to generate a new prototype for external linkage. + Function *PF = OpenModule->getFunction(FnName); + if (PF && !PF->empty()) { + ErrorF("redefinition of function across modules"); + return 0; + } + + // If we don't have a prototype yet, create one. + if (!PF) + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, + OpenModule); + return PF; + } + } + return NULL; +} + +Module *MCJITHelper::getModuleForNewFunction() { + // If we have a Module that hasn't been JITed, use that. + if (OpenModule) + return OpenModule; + + // Otherwise create a new Module. + std::string ModName = GenerateUniqueName("mcjit_module_"); + Module *M = new Module(ModName, Context); + Modules.push_back(M); + OpenModule = M; + return M; +} + +void *MCJITHelper::getPointerToFunction(Function* F) { + // Look for this function in an existing module + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + std::string FnName = F->getName(); + for (it = begin; it != end; ++it) { + Function *MF = (*it)->getFunction(FnName); + if (MF == F) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::closeCurrentModule() { + OpenModule = NULL; +} + +ExecutionEngine *MCJITHelper::compileModule(Module *M) { + if (M == OpenModule) + closeCurrentModule(); + + std::string ErrStr; + ExecutionEngine *NewEngine = EngineBuilder(M) + .setErrorStr(&ErrStr) + .setUseMCJIT(true) + .setMCJITMemoryManager(new HelpingMemoryManager(this)) + .create(); + if (!NewEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + // Create a function pass manager for this engine + FunctionPassManager *FPM = new FunctionPassManager(M); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + FPM->add(new DataLayout(*NewEngine->getDataLayout())); + // Provide basic AliasAnalysis support for GVN. + FPM->add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + FPM->add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + FPM->add(createInstructionCombiningPass()); + // Reassociate expressions. + FPM->add(createReassociatePass()); + // Eliminate Common SubExpressions. + FPM->add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // For each function in the module + Module::iterator it; + Module::iterator end = M->end(); + for (it = M->begin(); it != end; ++it) { + // Run the FPM on this function + FPM->run(*it); + } + + // We don't need this anymore + delete FPM; + + // Store this engine + EngineMap[M] = NewEngine; + NewEngine->finalizeObject(); + + return NewEngine; +} + +void *MCJITHelper::getPointerToNamedFunction(const std::string &Name) +{ + // Look for the functions in our modules, compiling only as necessary + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) { + Function *F = (*it)->getFunction(Name); + if (F && !F->empty()) { + std::map::iterator eeIt = EngineMap.find(*it); + if (eeIt != EngineMap.end()) { + void *P = eeIt->second->getPointerToFunction(F); + if (P) + return P; + } else { + ExecutionEngine *EE = compileModule(*it); + void *P = EE->getPointerToFunction(F); + if (P) + return P; + } + } + } + return NULL; +} + +void MCJITHelper::dump() +{ + ModuleVector::iterator begin = Modules.begin(); + ModuleVector::iterator end = Modules.end(); + ModuleVector::iterator it; + for (it = begin; it != end; ++it) + (*it)->dump(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static MCJITHelper *TheHelper; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +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]; + char ErrStr[256]; + sprintf(ErrStr, "Unknown variable name %s", Name.c_str()); + if (V == 0) return ErrorV(ErrStr); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheHelper->getFunction(MakeLegalFunctionName(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 = reinterpret_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 '/': return Builder.CreateFDiv(L, R, "divtmp"); + 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 = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheHelper->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, "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()), 2, + "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); + + std::string FnName = MakeLegalFunctionName(Name); + + Module* M = TheHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + + // If F conflicted, there was already something named 'FnName'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != FnName) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = M->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); + + 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 void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + TheHelper->closeCurrentModule(); + if (Function *LF = F->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read extern: "); + F->dump(); +#endif + } + } 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 = TheHelper->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; +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + fprintf(stderr, "Evaluated to %f\n", FP()); +#endif + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + 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", X); + return 0; +} + +extern "C" +double printlf() { + printf("\n"); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['/'] = 40; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "ready> "); +#endif + getNextToken(); + + // Make the helper, which holds all the code. + TheHelper = new MCJITHelper(Context); + + // Run the main "interpreter loop" now. + MainLoop(); + +#ifndef MINIMAL_STDERR_OUTPUT + // Print out all of the generated code. + TheHelper->dump(); +#endif + + return 0; +} diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h index 522803518398c..7af209bdfdce1 100644 --- a/include/llvm-c/BitReader.h +++ b/include/llvm-c/BitReader.h @@ -34,7 +34,7 @@ extern "C" { /* 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. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, char **OutMessage); @@ -44,7 +44,7 @@ LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, /** 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. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h index ba5a6778c9428..f605e2453f1c6 100644 --- a/include/llvm-c/BitWriter.h +++ b/include/llvm-c/BitWriter.h @@ -34,7 +34,7 @@ extern "C" { /*===-- Operations on modules ---------------------------------------------===*/ -/** Writes a module to the specified path. Returns 0 on success. */ +/** 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. */ @@ -42,7 +42,7 @@ 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. */ + descriptor. Returns 0 on success. Closes the Handle. */ int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); /** diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 6b62f33261ea1..9953d52edd624 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -165,7 +165,9 @@ typedef enum { a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. LLVMAddressSafety = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<33 + LLVMStackProtectStrongAttribute = 1ULL<<33, + LLVMCold = 1ULL << 34, + LLVMOptimizeNone = 1ULL << 35 */ } LLVMAttribute; @@ -220,6 +222,7 @@ typedef enum { LLVMPtrToInt = 39, LLVMIntToPtr = 40, LLVMBitCast = 41, + LLVMAddrSpaceCast = 60, /* Other Operators */ LLVMICmp = 42, @@ -272,7 +275,7 @@ typedef enum { LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something equivalent. */ - LLVMLinkOnceODRAutoHideLinkage, /**< Like LinkOnceODR, but possibly hidden. */ + LLVMLinkOnceODRAutoHideLinkage, /**< Obsolete */ LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ LLVMWeakODRLinkage, /**< Same, but only replaced by something equivalent. */ @@ -299,6 +302,8 @@ typedef enum { LLVMCCallConv = 0, LLVMFastCallConv = 8, LLVMColdCallConv = 9, + LLVMWebKitJSCallConv = 12, + LLVMAnyRegCallConv = 13, LLVMX86StdcallCallConv = 64, LLVMX86FastcallCallConv = 65 } LLVMCallConv; @@ -352,26 +357,26 @@ typedef enum { LLVMAtomicOrderingNotAtomic = 0, /**< A load or store which is not atomic */ LLVMAtomicOrderingUnordered = 1, /**< Lowest level of atomicity, guarantees somewhat sane results, lock free. */ - LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the - operations affecting a specific address, + LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the + operations affecting a specific address, a consistent ordering exists */ - LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort - necessary to acquire a lock to access other + LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort + necessary to acquire a lock to access other memory with normal loads and stores. */ - LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with - a barrier of the sort necessary to release + LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with + a barrier of the sort necessary to release a lock. */ - LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a - Release barrier (for fences and + LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a + Release barrier (for fences and operations which both read and write memory). */ - LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics - for loads and Release - semantics for stores. - Additionally, it guarantees - that a total ordering exists - between all - SequentiallyConsistent + LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics + for loads and Release + semantics for stores. + Additionally, it guarantees + that a total ordering exists + between all + SequentiallyConsistent operations. */ } LLVMAtomicOrdering; @@ -384,16 +389,16 @@ typedef enum { LLVMAtomicRMWBinOpOr, /**< OR a value and return the old one */ LLVMAtomicRMWBinOpXor, /**< Xor a value and return the old one */ LLVMAtomicRMWBinOpMax, /**< Sets the value if it's greater than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ } LLVMAtomicRMWBinOp; @@ -406,13 +411,37 @@ void LLVMInitializeCore(LLVMPassRegistryRef R); /** Deallocate and destroy all ManagedStatic variables. @see llvm::llvm_shutdown @see ManagedStatic */ -void LLVMShutdown(); +void LLVMShutdown(void); /*===-- Error handling ----------------------------------------------------===*/ +char *LLVMCreateMessage(const char *Message); void LLVMDisposeMessage(char *Message); +typedef void (*LLVMFatalErrorHandler)(const char *Reason); + +/** + * Install a fatal error handler. By default, if LLVM detects a fatal error, it + * will call exit(1). This may not be appropriate in many contexts. For example, + * doing exit(1) will bypass many crash reporting/tracing system tools. This + * function allows you to install a callback that will be invoked prior to the + * call to exit(1). + */ +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler); + +/** + * Reset the fatal error handler. This resets LLVM's fatal error handling + * behavior to the default. + */ +void LLVMResetFatalErrorHandler(void); + +/** + * Enable LLVM's built-in stack trace code. This intercepts the OS's crash + * signals and prints which component of LLVM you were in at the time if the + * crash. + */ +void LLVMEnablePrettyStackTrace(void); /** * @defgroup LLVMCCoreContext Contexts @@ -458,7 +487,7 @@ unsigned LLVMGetMDKindID(const char* Name, unsigned SLen); /** * @defgroup LLVMCCoreModule Modules * - * Modules represent the top-level structure in a LLVM program. An LLVM + * Modules represent the top-level structure in an LLVM program. An LLVM * module is effectively a translation unit or a collection of * translation units merged together. * @@ -537,6 +566,14 @@ void LLVMDumpModule(LLVMModuleRef M); LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char **ErrorMessage); +/** + * Return a string representation of the module. Use + * LLVMDisposeMessage to free the string. + * + * @see Module::print() + */ +char *LLVMPrintModuleToString(LLVMModuleRef M); + /** * Set inline assembly for a module. * @@ -688,6 +725,21 @@ LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty); */ LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); +/** + * Dump a representation of a type to stderr. + * + * @see llvm::Type::dump() + */ +void LLVMDumpType(LLVMTypeRef Val); + +/** + * Return a string representation of the type. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Type::print() + */ +char *LLVMPrintTypeToString(LLVMTypeRef Val); + /** * @defgroup LLVMCCoreTypeInt Integer Types * @@ -1039,7 +1091,7 @@ LLVMTypeRef LLVMX86MMXType(void); * hierarchy of classes within this type. Depending on the instance * obtained, not all APIs are available. * - * Callers can determine the type of a LLVMValueRef by calling the + * Callers can determine the type of an LLVMValueRef by calling the * LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These * functions are defined by a macro, so it isn't obvious which are * available by looking at the Doxygen source code. Instead, look at the @@ -1061,6 +1113,9 @@ LLVMTypeRef LLVMX86MMXType(void); macro(BlockAddress) \ macro(ConstantAggregateZero) \ macro(ConstantArray) \ + macro(ConstantDataSequential) \ + macro(ConstantDataArray) \ + macro(ConstantDataVector) \ macro(ConstantExpr) \ macro(ConstantFP) \ macro(ConstantInt) \ @@ -1105,6 +1160,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ + macro(AddrSpaceCastInst) \ macro(BitCastInst) \ macro(FPExtInst) \ macro(FPToSIInst) \ @@ -1159,6 +1215,14 @@ void LLVMSetValueName(LLVMValueRef Val, const char *Name); */ void LLVMDumpValue(LLVMValueRef Val); +/** + * Return a string representation of the value. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Value::print() + */ +char *LLVMPrintValueToString(LLVMValueRef Val); + /** * Replace all uses of a value with another one. * @@ -1179,7 +1243,7 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); /** * Convert value instances between types. * - * Internally, a LLVMValueRef is "pinned" to a specific type. This + * Internally, an LLVMValueRef is "pinned" to a specific type. This * series of functions allows you to cast an instance to a specific * type. * @@ -1201,7 +1265,7 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) * This module defines functions that allow you to inspect the uses of a * LLVMValueRef. * - * It is possible to obtain a LLVMUseRef for any LLVMValueRef instance. + * It is possible to obtain an LLVMUseRef for any LLVMValueRef instance. * Each LLVMUseRef (which corresponds to a llvm::Use instance) holds a * llvm::User and llvm::Value. * @@ -1568,6 +1632,7 @@ 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 LLVMConstAddrSpaceCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, @@ -1623,8 +1688,33 @@ 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); + +/** + * @defgroup LLVMCCoreValueWithAlignment Values with alignment + * + * Functions in this group only apply to values with alignment, i.e. + * global variables, load and store instructions. + */ + +/** + * Obtain the preferred alignment of the value. + * @see llvm::LoadInst::getAlignment() + * @see llvm::StoreInst::getAlignment() + * @see llvm::GlobalValue::getAlignment() + */ +unsigned LLVMGetAlignment(LLVMValueRef V); + +/** + * Set the preferred alignment of the value. + * @see llvm::LoadInst::setAlignment() + * @see llvm::StoreInst::setAlignment() + * @see llvm::GlobalValue::setAlignment() + */ +void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); + +/** + * @} + */ /** * @defgroup LLVMCoreValueConstantGlobalVariable Global Variables @@ -1804,7 +1894,7 @@ LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); /** * Obtain the function to which this argument belongs. * - * Unlike other functions in this group, this one takes a LLVMValueRef + * Unlike other functions in this group, this one takes an LLVMValueRef * that corresponds to a llvm::Attribute. * * The returned LLVMValueRef is the llvm::Function to which this @@ -1829,7 +1919,7 @@ LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); /** * Obtain the next parameter to a function. * - * This takes a LLVMValueRef obtained from LLVMGetFirstParam() (which is + * This takes an LLVMValueRef obtained from LLVMGetFirstParam() (which is * actually a wrapped iterator) and obtains the next parameter from the * underlying iterator. */ @@ -1978,12 +2068,12 @@ void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest); LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); /** - * Determine whether a LLVMValueRef is itself a basic block. + * Determine whether an LLVMValueRef is itself a basic block. */ LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); /** - * Convert a LLVMValueRef to a LLVMBasicBlockRef instance. + * Convert an LLVMValueRef to an LLVMBasicBlockRef instance. */ LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); @@ -2140,7 +2230,7 @@ LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); /** * Obtain the last instruction in a basic block. * - * The returned LLVMValueRef corresponds to a LLVM:Instruction. + * The returned LLVMValueRef corresponds to an LLVM:Instruction. */ LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); @@ -2322,12 +2412,12 @@ void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, unsigned LLVMCountIncoming(LLVMValueRef PhiNode); /** - * Obtain an incoming value to a PHI node as a LLVMValueRef. + * Obtain an incoming value to a PHI node as an LLVMValueRef. */ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); /** - * Obtain an incoming value to a PHI node as a LLVMBasicBlockRef. + * Obtain an incoming value to a PHI node as an LLVMBasicBlockRef. */ LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index); @@ -2518,6 +2608,8 @@ LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, @@ -2571,9 +2663,9 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, - LLVMValueRef PTR, LLVMValueRef Val, - LLVMAtomicOrdering ordering, +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, LLVMBool singleThread); /** @@ -2706,16 +2798,16 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); initialization succeeded. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_start_multithreaded */ -LLVMBool LLVMStartMultithreaded(); +LLVMBool LLVMStartMultithreaded(void); /** Deallocate structures necessary to make LLVM safe for multithreading. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_stop_multithreaded */ -void LLVMStopMultithreaded(); +void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. @see llvm::llvm_is_multithreaded */ -LLVMBool LLVMIsMultithreaded(); +LLVMBool LLVMIsMultithreaded(void); /** * @} diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index df65a7b20846b..79bcfcdab9e86 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -42,7 +42,7 @@ typedef void *LLVMDisasmContextRef; * instruction are specified by the Offset parameter and its byte widith is the * size parameter. For instructions sets with fixed widths and one symbolic * operand per instruction, the Offset parameter will be zero and Size parameter - * will be the instruction width. The information is returned in TagBuf and is + * will be the instruction width. The information is returned in TagBuf and is * Triple specific with its specific information defined by the value of * TagType for that Triple. If symbolic information is returned the function * returns 1, otherwise it returns 0. @@ -58,7 +58,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, * SubtractSymbol can be link edited independent of each other. Many other * platforms only allow a relocatable expression of the form AddSymbol + Offset * to be encoded. - * + * * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct * LLVMOpInfo1. The value of the relocatable expression for the operand, * including any PC adjustment, is passed in to the call back in the Value @@ -130,6 +130,17 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, /* The output reference is to a cstring address in a literal pool. */ #define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 +/* The output reference is to a Objective-C CoreFoundation string. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 +/* The output reference is to a Objective-C message. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 +/* The output reference is to a Objective-C message ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 +/* The output reference is to a Objective-C selector ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 +/* The output reference is to a Objective-C class ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8 + #ifdef __cplusplus extern "C" { #endif /* !defined(__cplusplus) */ @@ -170,6 +181,10 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); #define LLVMDisassembler_Option_PrintImmHex 2 /* The option use the other assembler printer variant */ #define LLVMDisassembler_Option_AsmPrinterVariant 4 +/* The option to set comment on instructions */ +#define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 /** * Dispose of a disassembler context. diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 8fae77def443b..35643122003a8 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -40,12 +40,14 @@ void LLVMLinkInInterpreter(void); typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; +typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; struct LLVMMCJITCompilerOptions { unsigned OptLevel; LLVMCodeModel CodeModel; LLVMBool NoFramePointerElim; LLVMBool EnableFastISel; + LLVMMCJITMemoryManagerRef MCJMM; }; /*===-- Operations on generic values --------------------------------------===*/ @@ -167,12 +169,44 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +/*===-- Operations on memory managers -------------------------------------===*/ + +typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName); +typedef uint8_t *(*LLVMMemoryManagerAllocateDataSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName, LLVMBool IsReadOnly); +typedef LLVMBool (*LLVMMemoryManagerFinalizeMemoryCallback)( + void *Opaque, char **ErrMsg); +typedef void (*LLVMMemoryManagerDestroyCallback)(void *Opaque); + +/** + * Create a simple custom MCJIT memory manager. This memory manager can + * intercept allocations in a module-oblivious way. This will return NULL + * if any of the passed functions are NULL. + * + * @param Opaque An opaque client object to pass back to the callbacks. + * @param AllocateCodeSection Allocate a block of memory for executable code. + * @param AllocateDataSection Allocate a block of memory for data. + * @param FinalizeMemory Set page permissions and flush cache. Return 0 on + * success, 1 on error. + */ +LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( + void *Opaque, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy); + +void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); + /** * @} */ #ifdef __cplusplus -} +} #endif /* defined(__cplusplus) */ #endif diff --git a/include/llvm-c/IRReader.h b/include/llvm-c/IRReader.h new file mode 100644 index 0000000000000..d0a23be0abf5d --- /dev/null +++ b/include/llvm-c/IRReader.h @@ -0,0 +1,40 @@ +/*===-- llvm-c/IRReader.h - IR Reader 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 file defines the C interface to the IR Reader. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_IRREADER_H +#define LLVM_C_IRREADER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Read LLVM IR from a memory buffer and convert it into an in-memory Module + * object. Returns 0 on success. + * Optionally returns a human-readable description of any errors that + * occured during parsing IR. OutMessage must be disposed with + * LLVMDisposeMessage. + * + * @see llvm::ParseIR() + */ +LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm-c/LinkTimeOptimizer.h b/include/llvm-c/LinkTimeOptimizer.h index 7a0fbf65bedbf..8bcf59969ccb9 100644 --- a/include/llvm-c/LinkTimeOptimizer.h +++ b/include/llvm-c/LinkTimeOptimizer.h @@ -4,7 +4,7 @@ // // 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 @@ -46,7 +46,7 @@ extern "C" { // 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. diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index ecccfeed7f54b..c271552482e0b 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -100,4 +100,3 @@ const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI); #endif /* defined(__cplusplus) */ #endif - diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h new file mode 100644 index 0000000000000..7f03ede604a26 --- /dev/null +++ b/include/llvm-c/Support.h @@ -0,0 +1,35 @@ +/*===-- llvm-c/Support.h - Support 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 file defines the C interface to the LLVM support library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_SUPPORT_H +#define LLVM_C_SUPPORT_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function permanently loads the dynamic library at the given path. + * It is safe to call this function multiple times for the same library. + * + * @see sys::DynamicLibrary::LoadLibraryPermanently() + */ +LLVMBool LLVMLoadLibraryPermanently(const char* Filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 80fc3e5ad72c0..b465b4b88db51 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -22,6 +22,10 @@ #include "llvm-c/Core.h" #include "llvm/Config/llvm-config.h" +#if defined(_MSC_VER) && !defined(inline) +#define inline __inline +#endif + #ifdef __cplusplus extern "C" { #endif @@ -37,14 +41,13 @@ enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef; -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 */ @@ -53,7 +56,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##TargetMC(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ - + /* Declare all of the available assembly printer initialization functions. */ #define LLVM_ASM_PRINTER(TargetName) \ void LLVMInitialize##TargetName##AsmPrinter(void); @@ -71,7 +74,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##Disassembler(void); #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* 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. */ @@ -98,7 +101,7 @@ static inline void LLVMInitializeAllTargetMCs(void) { #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmPrinters - 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. */ @@ -107,7 +110,7 @@ static inline void LLVMInitializeAllAsmPrinters(void) { #include "llvm/Config/AsmPrinters.def" #undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmParsers - 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. */ @@ -116,7 +119,7 @@ static inline void LLVMInitializeAllAsmParsers(void) { #include "llvm/Config/AsmParsers.def" #undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllDisassemblers - 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. */ @@ -126,9 +129,9 @@ static inline void LLVMInitializeAllDisassemblers(void) { #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* 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 + 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. */ @@ -140,7 +143,43 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) { #else return 1; #endif -} +} + +/** LLVMInitializeNativeTargetAsmParser - The main program should call this + function to initialize the parser for the native target corresponding to the + host. */ +static inline LLVMBool LLVMInitializeNativeAsmParser(void) { +#ifdef LLVM_NATIVE_ASMPARSER + LLVM_NATIVE_ASMPARSER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetAsmPrinter - The main program should call this + function to initialize the printer for the native target corresponding to + the host. */ +static inline LLVMBool LLVMInitializeNativeAsmPrinter(void) { +#ifdef LLVM_NATIVE_ASMPRINTER + LLVM_NATIVE_ASMPRINTER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetDisassembler - The main program should call this + function to initialize the disassembler for the native target corresponding + to the host. */ +static inline LLVMBool LLVMInitializeNativeDisassembler(void) { +#ifdef LLVM_NATIVE_DISASSEMBLER + LLVM_NATIVE_DISASSEMBLER(); + return 0; +#else + return 1; +#endif +} /*===-- Target Data -------------------------------------------------------===*/ @@ -151,83 +190,94 @@ 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); +void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM); /** Adds target library information to a pass manager. This does not take ownership of the target library info. See the method llvm::PassManagerBase::add. */ -void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef); +void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef TLI, + LLVMPassManagerRef PM); /** Converts target data to a target layout string. The string must be disposed with LLVMDisposeMessage. See the constructor llvm::DataLayout::DataLayout. */ -char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD); /** Returns the byte order of a target, either LLVMBigEndian or LLVMLittleEndian. See the method llvm::DataLayout::isLittleEndian. */ -enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); +enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSize(LLVMTargetDataRef); +unsigned LLVMPointerSize(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target for a specified address space. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSizeForAS(LLVMTargetDataRef, unsigned AS); +unsigned LLVMPointerSizeForAS(LLVMTargetDataRef TD, unsigned AS); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD); + +/** Returns the integer type that is the same size as a pointer on a target. + This version allows the address space to be specified. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef TD, unsigned AS); /** Returns the integer type that is the same size as a pointer on a target. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); +LLVMTypeRef LLVMIntPtrTypeInContext(LLVMContextRef C, LLVMTargetDataRef TD); /** Returns the integer type that is the same size as a pointer on a target. This version allows the address space to be specified. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef, unsigned AS); +LLVMTypeRef LLVMIntPtrTypeForASInContext(LLVMContextRef C, LLVMTargetDataRef TD, + unsigned AS); /** Computes the size of a type in bytes for a target. See the method llvm::DataLayout::getTypeSizeInBits. */ -unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the storage size of a type in bytes for a target. See the method llvm::DataLayout::getTypeStoreSize. */ -unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI size of a type in bytes for a target. See the method llvm::DataLayout::getTypeAllocSize. */ -unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the call frame alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a global variable in bytes for a target. See the method llvm::DataLayout::getPreferredAlignment. */ -unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, 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 LLVMElementAtOffset(LLVMTargetDataRef TD, 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); +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, + LLVMTypeRef StructTy, unsigned Element); /** Deallocates a TargetData. See the destructor llvm::DataLayout::~DataLayout. */ -void LLVMDisposeTargetData(LLVMTargetDataRef); +void LLVMDisposeTargetData(LLVMTargetDataRef TD); /** * @} diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index 5e355959f6429..e1594113949cd 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -57,11 +57,21 @@ typedef enum { } LLVMCodeGenFileType; /** Returns the first llvm::Target in the registered targets list. */ -LLVMTargetRef LLVMGetFirstTarget(); +LLVMTargetRef LLVMGetFirstTarget(void); /** Returns the next llvm::Target given a previous one (or null if there's none) */ LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T); /*===-- Target ------------------------------------------------------------===*/ +/** Finds the target corresponding to the given name and stores it in \p T. + Returns 0 on success. */ +LLVMTargetRef LLVMGetTargetFromName(const char *Name); + +/** Finds the target corresponding to the given triple and stores it in \p T. + Returns 0 on success. Optionally returns any error in ErrorMessage. + Use LLVMDisposeMessage to dispose the message. */ +LLVMBool LLVMGetTargetFromTriple(const char* Triple, LLVMTargetRef *T, + char **ErrorMessage); + /** Returns the name of a target. See llvm::Target::getName */ const char *LLVMGetTargetName(LLVMTargetRef T); @@ -79,9 +89,9 @@ LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T); /*===-- Target Machine ----------------------------------------------------===*/ /** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */ -LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char *Triple, - char *CPU, char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, - LLVMCodeModel CodeModel); +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, + const char *Triple, const char *CPU, const char *Features, + LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel); /** Dispose the LLVMTargetMachineRef instance generated by LLVMCreateTargetMachine. */ @@ -108,6 +118,10 @@ char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T); /** Returns the llvm::DataLayout used for this llvm:TargetMachine. */ LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); +/** Set the target machine's ASM verbosity. */ +void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, + LLVMBool VerboseAsm); + /** Emits an asm or object file for the given module to the filename. This wraps several c++ only classes (among them a file stream). Returns any error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */ @@ -117,6 +131,12 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, /** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf); + +/*===-- Triple ------------------------------------------------------------===*/ +/** Get a triple for the host machine as a string. The result needs to be + disposed with LLVMDisposeMessage. */ +char* LLVMGetDefaultTargetTriple(void); + #ifdef __cplusplus } #endif diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index a2c4d6116f03d..355e8dc299fb9 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -65,6 +65,9 @@ void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM); /** See llvm::createLoopRotatePass function. */ void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); +/** See llvm::createLoopRerollPass function. */ +void LLVMAddLoopRerollPass(LLVMPassManagerRef PM); + /** See llvm::createLoopUnrollPass function. */ void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); @@ -74,6 +77,9 @@ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); /** See llvm::createMemCpyOptPass function. */ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); +/** See llvm::createPartiallyInlineLibCallsPass function. */ +void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); + /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 40110fddfc139..89f54b7a7b747 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -16,9 +16,22 @@ #ifndef LLVM_C_LTO_H #define LLVM_C_LTO_H -#include #include -#include +#include + +#ifndef __cplusplus +#if !defined(_MSC_VER) +#include +typedef bool lto_bool_t; +#else +/* MSVC in particular does not have anything like _Bool or bool in C, but we can + at least make sure the type is the same size. The implementation side will + use C++ bool. */ +typedef unsigned char lto_bool_t; +#endif +#else +typedef bool lto_bool_t; +#endif /** * @defgroup LLVMCLTO LTO @@ -27,7 +40,7 @@ * @{ */ -#define LTO_API_VERSION 4 +#define LTO_API_VERSION 5 typedef enum { LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ @@ -87,14 +100,14 @@ lto_get_error_message(void); /** * Checks if a file is a loadable object file. */ -extern bool +extern lto_bool_t lto_module_is_object_file(const char* path); /** * Checks if a file is a loadable object compiled for requested target. */ -extern bool +extern lto_bool_t lto_module_is_object_file_for_target(const char* path, const char* target_triple_prefix); @@ -102,14 +115,14 @@ lto_module_is_object_file_for_target(const char* path, /** * Checks if a buffer is a loadable object file. */ -extern bool +extern lto_bool_t 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 +extern lto_bool_t lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, const char* target_triple_prefix); @@ -208,7 +221,7 @@ 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 +extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); @@ -217,7 +230,7 @@ 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 +extern lto_bool_t lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); @@ -225,7 +238,7 @@ 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 +extern lto_bool_t lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); @@ -251,9 +264,8 @@ 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. + * Tells LTO optimization passes that this symbol must be preserved + * because it is referenced by native code or a command line option. */ extern void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); @@ -263,7 +275,7 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); * merged contents of all modules added so far. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** @@ -281,7 +293,7 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); * Generates code for all added modules into one native object file. * The name of the file is written to name. Returns true on error. */ -extern bool +extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 14bcaef6d1656..43a78660bf186 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -6,461 +6,575 @@ // 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. -// +/// +/// \file +/// \brief +/// 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_ADT_APFLOAT_H #define LLVM_ADT_APFLOAT_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 APSInt; - 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 +struct fltSemantics; +class APSInt; +class StringRef; + +/// Enum that represents what fraction of the LSB truncated bits of an fp number +/// represent. +/// +/// This 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 +}; + +/// \brief A self-contained host- and target-independent arbitrary-precision +/// floating-point software implementation. +/// +/// APFloat 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. +/// +/// APFloat does not provide any exception handling beyond default exception +/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause +/// by encoding Signaling NaNs with the first bit of its trailing significand as +/// 0. +/// +/// 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, nexttoward. +/// +class APFloat { +public: + + /// A signed type to represent a floating point numbers unbiased exponent. + typedef signed short ExponentType; + + /// \name 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; + + /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with + /// anything real. + static const fltSemantics Bogus; + + /// @} + + static unsigned int semanticsPrecision(const fltSemantics &); + + /// IEEE-754R 5.11: Floating Point Comparison Relations. + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered }; - 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); - APFloat(const fltSemantics &, const APInt &); - explicit APFloat(double d); - explicit APFloat(float f); - 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); - } + /// IEEE-754R 4.3: Rounding-direction attributes. + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; - /// getSNan - Factory for SNaN values. - static APFloat getSNaN(const fltSemantics &Sem, - bool Negative = false, - const APInt *payload = 0) { - return makeNaN(Sem, true, Negative, payload); - } + /// IEEE-754R 7: Default exception handling. + /// + /// opUnderflow or opOverflow are always returned or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; - /// 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); - opStatus roundToIntegral(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 convertToInteger(APSInt&, 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 LLVM_DELETED_FUNCTION; - - /* 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 isNormal() const { return category == fcNormal; } - 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(); } - bool isDenormal() const; - - APFloat& operator=(const APFloat &); - - /// \brief Overload to compute a hash code for an APFloat value. - /// - /// Note that the use of hash codes for floating point values is in general - /// frought with peril. Equality is hard to define for these values. For - /// example, should negative and positive zero hash to different codes? Are - /// they equal or not? This hash value implementation specifically - /// emphasizes producing different codes for different inputs in order to - /// be used in canonicalization and memoization. As such, equality is - /// bitwiseIsEqual, and 0 != -0. - friend hash_code hash_value(const APFloat &Arg); - - /// 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; - - /// getExactInverse - If this value has an exact multiplicative inverse, - /// store it in inv and return true. - bool getExactInverse(APFloat *inv) 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 fltSemantics *Sem, const APInt& api); - 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; + /// Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero }; - // See friend declaration above. This additional declaration is required in - // order to compile LLVM with IBM xlC compiler. - hash_code hash_value(const APFloat &Arg); -} /* namespace llvm */ + /// Convenience enum used to construct an uninitialized APFloat. + enum uninitializedTag { + uninitialized + }; -#endif /* LLVM_ADT_APFLOAT_H */ + /// \name Constructors + /// @{ + + APFloat(const fltSemantics &); // Default construct to 0.0 + APFloat(const fltSemantics &, StringRef); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, uninitializedTag); + APFloat(const fltSemantics &, const APInt &); + explicit APFloat(double d); + explicit APFloat(float f); + APFloat(const APFloat &); + ~APFloat(); + + /// @} + + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return partCount() > 1; } + + /// \name Convenience "constructors" + /// @{ + + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// 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); + } + } + + /// Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, false, Negative, payload); + } + + /// Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, true, Negative, payload); + } + + /// 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); + + /// 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); + + /// 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); + + /// 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); + + /// @} + + /// 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); + + /// \name 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); + opStatus roundToIntegral(roundingMode); + /// IEEE-754R 5.3.1: nextUp/nextDown. + opStatus next(bool nextDown); + + /// @} + + /// \name Sign operations. + /// @{ + + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /// @} + + /// \name Conversions + /// @{ + + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode, + bool *) const; + opStatus convertToInteger(APSInt &, 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 LLVM_DELETED_FUNCTION; + + /// 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; + + /// \name IEEE-754R 5.7.2 General operations. + /// @{ + + /// IEEE-754R isSignMinus: Returns true if and only if the current value is + /// negative. + /// + /// This applies to zeros and NaNs as well. + bool isNegative() const { return sign; } + + /// IEEE-754R isNormal: Returns true if and only if the current value is normal. + /// + /// This implies that the current value of the float is not zero, subnormal, + /// infinite, or NaN following the definition of normality from IEEE-754R. + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + + /// Returns true if and only if the current value is zero, subnormal, or + /// normal. + /// + /// This means that the value is not infinite or NaN. + bool isFinite() const { return !isNaN() && !isInfinity(); } + + /// Returns true if and only if the float is plus or minus zero. + bool isZero() const { return category == fcZero; } + + /// IEEE-754R isSubnormal(): Returns true if and only if the float is a + /// denormal. + bool isDenormal() const; + + /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity. + bool isInfinity() const { return category == fcInfinity; } + + /// Returns true if and only if the float is a quiet or signaling NaN. + bool isNaN() const { return category == fcNaN; } + + /// Returns true if and only if the float is a signaling NaN. + bool isSignaling() const; + + /// @} + + /// \name Simple Queries + /// @{ + + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isNonZero() const { return category != fcZero; } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + /// Returns true if and only if the number has the smallest possible non-zero + /// magnitude in the current semantics. + bool isSmallest() const; + + /// Returns true if and only if the number has the largest possible finite + /// magnitude in the current semantics. + bool isLargest() const; + + /// @} + + APFloat &operator=(const APFloat &); + + /// \brief Overload to compute a hash code for an APFloat value. + /// + /// Note that the use of hash codes for floating point values is in general + /// frought with peril. Equality is hard to define for these values. For + /// example, should negative and positive zero hash to different codes? Are + /// they equal or not? This hash value implementation specifically + /// emphasizes producing different codes for different inputs in order to + /// be used in canonicalization and memoization. As such, equality is + /// bitwiseIsEqual, and 0 != -0. + friend hash_code hash_value(const APFloat &Arg); + + /// 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; + + /// If this value has an exact multiplicative inverse, store it in inv and + /// return true. + bool getExactInverse(APFloat *inv) const; + +private: + + /// \name Simple Queries + /// @{ + + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /// @} + + /// \name 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(); + /// Return true if the significand excluding the integral bit is all ones. + bool isSignificandAllOnes() const; + /// Return true if the significand excluding the integral bit is all zeros. + bool isSignificandAllZeros() const; + + /// @} + + /// \name Arithmetic on special values. + /// @{ + + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /// @} + + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); + static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + + /// @} + + /// \name Miscellany + /// @{ + + bool convertFromStringSpecials(StringRef str); + 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 fltSemantics *Sem, const APInt &api); + 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(); + + /// The semantics that this value obeys. + const fltSemantics *semantics; + + /// A binary fraction with an explicit integer bit. + /// + /// The significand must be at least one bit wider than the target precision. + union Significand { + integerPart part; + integerPart *parts; + } significand; + + /// The signed unbiased exponent of the value. + ExponentType 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; + + /// Sign bit of the number. + unsigned int sign : 1; +}; + +/// See friend declaration above. +/// +/// This additional declaration is required in order to compile LLVM with IBM +/// xlC compiler. +hash_code hash_value(const APFloat &Arg); +} // namespace llvm + +#endif // LLVM_ADT_APFLOAT_H diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 3d8b72d9aaf4d..d494ad25351bd 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file implements a class to represent arbitrary precision integral -// constant values and operations on them. -// +/// +/// \file +/// \brief This file implements a class to represent arbitrary precision +/// integral constant values and operations on them. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_APINT_H @@ -24,30 +25,30 @@ #include namespace llvm { - class Deserializer; - class FoldingSetNodeID; - class Serializer; - class StringRef; - class hash_code; - class raw_ostream; +class Deserializer; +class FoldingSetNodeID; +class Serializer; +class StringRef; +class hash_code; +class raw_ostream; - template - class SmallVectorImpl; +template class SmallVectorImpl; - // An unsigned host type used as a single part of a multi-part - // bignum. - typedef uint64_t integerPart; +// 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)); +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 +/// \brief Class for arbitrary precision integers. +/// +/// APInt 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 @@ -71,65 +72,68 @@ namespace llvm { /// * 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. + 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. + 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, + APINT_BITS_PER_WORD = + static_cast(sizeof(uint64_t)) * CHAR_BIT, /// Byte size of a word APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) }; + /// \brief Fast internal constructor + /// /// 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) { } + 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; - } + /// \brief Determine if this APInt just has one word to store value. + /// + /// \returns true if the number of bits <= 64, false otherwise. + 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. + /// \brief Determine which word a bit is in. + /// + /// \returns the word position for the specified bit position. static unsigned whichWord(unsigned bitPosition) { return bitPosition / APINT_BITS_PER_WORD; } - /// @returns the bit position in a word for the specified bit position + /// \brief Determine which bit in a word a bit is in. + /// + /// \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; } + /// \brief Get a single bit mask. + /// + /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set /// 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); } + /// \brief Clear unused high order bits + /// /// 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() { + APInt &clearUnusedBits() { // Compute how many bits are used in the final word unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; if (wordBits == 0) @@ -147,12 +151,15 @@ class APInt { return *this; } - /// @returns the corresponding word for the specified bit position. - /// @brief Get the word corresponding to a bit position + /// \brief Get the word corresponding to a bit position + /// \returns the corresponding word for the specified bit position. uint64_t getWord(unsigned bitPosition) const { return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; } + /// \brief Convert a char array into an APInt + /// + /// \param radix 2, 8, 10, 16, or 36 /// 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. @@ -162,19 +169,16 @@ class APInt { /// 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, 16, or 36 - /// @brief Convert a char array into an APInt void fromString(unsigned numBits, StringRef str, uint8_t radix); + /// \brief An internal division function for dividing APInts. + /// /// 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); + 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); @@ -183,25 +187,25 @@ class APInt { void initFromArray(ArrayRef array); /// out-of-line slow case for inline copy constructor - void initSlowCase(const APInt& that); + 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; + APInt AndSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator| - APInt OrSlowCase(const APInt& RHS) const; + APInt OrSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator^ - APInt XorSlowCase(const APInt& RHS) const; + APInt XorSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator= - APInt& AssignSlowCase(const APInt& RHS); + APInt &AssignSlowCase(const APInt &RHS); /// out-of-line slow case for operator== - bool EqualSlowCase(const APInt& RHS) const; + bool EqualSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator== bool EqualSlowCase(uint64_t Val) const; @@ -216,18 +220,21 @@ class APInt { unsigned countPopulationSlowCase() const; public: - /// @name Constructors + /// \name Constructors /// @{ + + /// \brief Create a new APInt of numBits width, initialized as val. + /// /// 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. + /// + /// \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 APInt(unsigned numBits, uint64_t val, bool isSigned = false) - : BitWidth(numBits), VAL(0) { + : BitWidth(numBits), VAL(0) { assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = val; @@ -236,12 +243,15 @@ public: clearUnusedBits(); } + /// \brief Construct an APInt of numBits width, initialized as bigVal[]. + /// /// Note that bigVal.size() 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 bigVal a sequence of words to form the initial value of the APInt - /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + /// + /// \param numBits the bit width of the constructed APInt + /// \param bigVal a sequence of words to form the initial value of the APInt APInt(unsigned numBits, ArrayRef bigVal); + /// Equivalent to APInt(numBits, ArrayRef(bigVal, numWords)), but /// deprecated because this constructor is prone to ambiguity with the /// APInt(unsigned, uint64_t, bool) constructor. @@ -251,22 +261,22 @@ public: /// constructor. APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + /// \brief Construct an APInt from a string representation. + /// /// This constructor interprets the string \p 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, 16, and 36. It is an error for the value implied by the + /// are 2, 8, 10, 16, and 36. 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. + /// \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 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) { + APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; @@ -275,207 +285,228 @@ public: } #if LLVM_HAS_RVALUE_REFERENCES - /// @brief Move Constructor. - APInt(APInt&& that) : BitWidth(that.BitWidth), VAL(that.VAL) { + /// \brief Move Constructor. + APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) { that.BitWidth = 0; } #endif - /// @brief Destructor. + /// \brief Destructor. ~APInt() { - if (!isSingleWord()) - delete [] pVal; + if (needsCleanup()) + delete[] pVal; } - /// Default constructor that creates an uninitialized APInt. This is useful - /// for object deserialization (pair this with the static method Read). + /// \brief 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; + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return !isSingleWord(); } + + /// Used to insert APInt objects, or objects that contain APInt objects, into + /// FoldingSets. + void Profile(FoldingSetNodeID &id) const; /// @} - /// @name Value Tests + /// \name Value Tests /// @{ + + /// \brief Determine sign of this APInt. + /// /// 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]; - } + /// + /// \returns true if this APInt is negative, false otherwise + bool isNegative() const { return (*this)[BitWidth - 1]; } + /// \brief Determine if this APInt Value is non-negative (>= 0) + /// /// 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(); - } + bool isNonNegative() const { return !isNegative(); } + /// \brief Determine if this APInt Value is positive. + /// /// 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; - } + /// + /// \returns true if this APInt is positive. + bool isStrictlyPositive() const { return isNonNegative() && !!*this; } + /// \brief Determine if all bits are set + /// /// 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; + if (isSingleWord()) + return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth); + return countPopulationSlowCase() == BitWidth; } + /// \brief Determine if this is the largest unsigned value. + /// /// 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; - } + bool isMaxValue() const { return isAllOnesValue(); } + /// \brief Determine if this is the largest signed value. + /// /// 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; + return BitWidth == 1 ? VAL == 0 + : !isNegative() && countPopulation() == BitWidth - 1; } + /// \brief Determine if this is the smallest unsigned value. + /// /// 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; - } + bool isMinValue() const { return !*this; } + /// \brief Determine if this is the smallest signed value. + /// /// 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. + /// \brief Check if this APInt has an N-bits unsigned integer value. bool isIntN(unsigned N) const { assert(N && "N == 0 ???"); return getActiveBits() <= N; } - /// @brief Check if this APInt has an N-bits signed integer value. + /// \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. + /// \brief Check if this APInt's value is a power of two greater than zero. + /// + /// \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. + /// \brief Check if the APInt's value is returned by getSignBit. + /// + /// \returns true if this is the value returned by getSignBit. bool isSignBit() const { return isMinSignedValue(); } + /// \brief Convert APInt to a boolean value. + /// /// This converts the APInt to a boolean value as a test against zero. - /// @brief Boolean conversion function. - bool getBoolValue() const { - return !!*this; - } + 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. + /// 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(); + return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit + : getZExtValue(); } /// @} - /// @name Value Generators + /// \name Value Generators /// @{ - /// @brief Gets maximum unsigned value of APInt for specific bit width. + + /// \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. + /// \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 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. + /// \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. + /// \brief Get the SignBit for a specific bit width. + /// + /// This is just a wrapper function of getSignedMinValue(), and it helps code + /// readability when we want to get a SignBit. 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. + /// \brief Get the all-ones value. + /// + /// \returns the all-ones value for an APInt of the specified bit-width. static APInt getAllOnesValue(unsigned numBits) { return APInt(numBits, UINT64_MAX, 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); - } + /// \brief Get the '0' value. + /// + /// \returns the '0' value for an APInt of the specified bit-width. + static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); } + /// \brief Compute an APInt containing numBits highbits from this APInt. + /// /// 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. + /// + /// \returns the high "numBits" bits of this APInt. APInt getHiBits(unsigned numBits) const; + /// \brief Compute an APInt containing numBits lowbits from this APInt. + /// /// Get an APInt with the same BitWidth as this APInt, just zero mask /// the high bits. - /// @returns the low "numBits" bits of this APInt. + /// + /// \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. + /// \brief 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; } - + + /// \brief Get a value with a block of bits set. + /// /// 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. + /// + /// \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. 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); + getHighBitsSet(numBits, numBits - loBit); + return getLowBitsSet(numBits, hiBit - loBit).shl(loBit); } + /// \brief Get a value with high bits set + /// /// 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 + /// + /// \param numBits the bitwidth of the result + /// \param hiBitsSet the number of high-order bits set in the result. 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 @@ -488,10 +519,12 @@ public: return getAllOnesValue(numBits).shl(shiftAmt); } + /// \brief Get a value with low bits set + /// /// 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 + /// + /// \param numBits the bitwidth of the result + /// \param loBitsSet the number of low-order bits set in the result. 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 @@ -527,65 +560,74 @@ public: return I1.zext(I2.getBitWidth()) == I2; } - + /// \brief Overload to compute a hash_code for an APInt value. friend hash_code hash_value(const APInt &Arg); /// 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 { + const uint64_t *getRawData() const { if (isSingleWord()) return &VAL; return &pVal[0]; } /// @} - /// @name Unary Operators + /// \name Unary Operators /// @{ - /// @returns a new APInt value representing *this incremented by one - /// @brief Postfix increment operator. + + /// \brief Postfix increment operator. + /// + /// \returns a new APInt value representing *this incremented by one const APInt operator++(int) { APInt API(*this); ++(*this); return API; } - /// @returns *this incremented by one - /// @brief Prefix increment operator. - APInt& operator++(); + /// \brief Prefix increment operator. + /// + /// \returns *this incremented by one + APInt &operator++(); - /// @returns a new APInt representing *this decremented by one. - /// @brief Postfix decrement operator. + /// \brief Postfix decrement operator. + /// + /// \returns a new APInt representing *this decremented by one. const APInt operator--(int) { APInt API(*this); --(*this); return API; } - /// @returns *this decremented by one. - /// @brief Prefix decrement operator. - APInt& operator--(); + /// \brief Prefix decrement operator. + /// + /// \returns *this decremented by one. + APInt &operator--(); + /// \brief Unary bitwise complement operator. + /// /// Performs a bitwise complement operation on this APInt. - /// @returns an APInt that is the bitwise complement of *this - /// @brief Unary bitwise complement operator. + /// + /// \returns an APInt that is the bitwise complement of *this APInt operator~() const { APInt Result(*this); Result.flipAllBits(); return Result; } + /// \brief Unary negation operator + /// /// 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); - } + /// + /// \returns An APInt value representing the negation of *this. + APInt operator-() const { return APInt(BitWidth, 0) - (*this); } + /// \brief Logical negation operator. + /// /// Performs logical negation operation on this APInt. - /// @returns true if *this is zero, false otherwise. - /// @brief Logical negation operator. + /// + /// \returns true if *this is zero, false otherwise. bool operator!() const { if (isSingleWord()) return !VAL; @@ -597,11 +639,13 @@ public: } /// @} - /// @name Assignment Operators + /// \name Assignment Operators /// @{ - /// @returns *this after assignment of RHS. - /// @brief Copy assignment operator. - APInt& operator=(const APInt& RHS) { + + /// \brief Copy assignment operator. + /// + /// \returns *this after assignment of RHS. + APInt &operator=(const APInt &RHS) { // If the bitwidths are the same, we can avoid mucking with memory if (isSingleWord() && RHS.isSingleWord()) { VAL = RHS.VAL; @@ -614,9 +658,9 @@ public: #if LLVM_HAS_RVALUE_REFERENCES /// @brief Move assignment operator. - APInt& operator=(APInt&& that) { + APInt &operator=(APInt &&that) { if (!isSingleWord()) - delete [] pVal; + delete[] pVal; BitWidth = that.BitWidth; VAL = that.VAL; @@ -627,31 +671,37 @@ public: } #endif + /// \brief Assignment operator. + /// /// 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); + /// + /// \returns *this after assignment of RHS value. + APInt &operator=(uint64_t RHS); + /// \brief Bitwise AND assignment operator. + /// /// 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); + /// + /// \returns *this after ANDing with RHS. + APInt &operator&=(const APInt &RHS); + /// \brief Bitwise OR assignment operator. + /// /// 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); + /// + /// \returns *this after ORing with RHS. + APInt &operator|=(const APInt &RHS); + /// \brief Bitwise OR assignment operator. + /// /// 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) { + APInt &operator|=(uint64_t RHS) { if (isSingleWord()) { VAL |= RHS; clearUnusedBits(); @@ -661,114 +711,149 @@ public: return *this; } + /// \brief Bitwise XOR assignment operator. + /// /// 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); + /// + /// \returns *this after XORing with RHS. + APInt &operator^=(const APInt &RHS); + /// \brief Multiplication assignment operator. + /// /// Multiplies this APInt by RHS and assigns the result to *this. - /// @returns *this - /// @brief Multiplication assignment operator. - APInt& operator*=(const APInt& RHS); + /// + /// \returns *this + APInt &operator*=(const APInt &RHS); + /// \brief Addition assignment operator. + /// /// Adds RHS to *this and assigns the result to *this. - /// @returns *this - /// @brief Addition assignment operator. - APInt& operator+=(const APInt& RHS); + /// + /// \returns *this + APInt &operator+=(const APInt &RHS); + /// \brief Subtraction assignment operator. + /// /// Subtracts RHS from *this and assigns the result to *this. - /// @returns *this - /// @brief Subtraction assignment operator. - APInt& operator-=(const APInt& RHS); + /// + /// \returns *this + APInt &operator-=(const APInt &RHS); + /// \brief Left-shift assignment function. + /// /// 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) { + /// + /// \returns *this after shifting left by shiftAmt + APInt &operator<<=(unsigned shiftAmt) { *this = shl(shiftAmt); return *this; } /// @} - /// @name Binary Operators + /// \name Binary Operators /// @{ + + /// \brief Bitwise AND operator. + /// /// 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 { + /// + /// \returns An APInt value representing the bitwise AND of *this and RHS. + 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 { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const { return this->operator&(RHS); } + /// \brief Bitwise OR operator. + /// /// 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 { + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + 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 { + + /// \brief Bitwise OR function. + /// + /// Performs a bitwise or on *this and RHS. This is implemented bny simply + /// calling operator|. + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const { return this->operator|(RHS); } + /// \brief Bitwise XOR operator. + /// /// 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 { + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + 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 { + + /// \brief Bitwise XOR function. + /// + /// Performs a bitwise XOR operation on *this and RHS. This is implemented + /// through the usage of operator^. + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const { return this->operator^(RHS); } + /// \brief Multiplication operator. + /// /// Multiplies this APInt by RHS and returns the result. - /// @brief Multiplication operator. - APInt operator*(const APInt& RHS) const; + APInt operator*(const APInt &RHS) const; + /// \brief Addition operator. + /// /// 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); - } + APInt operator+(const APInt &RHS) const; + APInt operator+(uint64_t RHS) const { return (*this) + APInt(BitWidth, RHS); } + /// \brief Subtraction operator. + /// /// 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-(const APInt &RHS) const; + APInt operator-(uint64_t RHS) const { return (*this) - APInt(BitWidth, RHS); } - APInt operator<<(unsigned Bits) const { - return shl(Bits); - } + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(unsigned Bits) const { return shl(Bits); } - APInt operator<<(const APInt &Bits) const { - return shl(Bits); - } + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(const APInt &Bits) const { return shl(Bits); } + /// \brief Arithmetic right-shift function. + /// /// Arithmetic right-shift this APInt by shiftAmt. - /// @brief Arithmetic right-shift function. - APInt ashr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const; + /// \brief Logical right-shift function. + /// /// Logical right-shift this APInt by shiftAmt. - /// @brief Logical right-shift function. - APInt lshr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const; + /// \brief Left-shift function. + /// /// Left-shift this APInt by shiftAmt. - /// @brief Left-shift function. - APInt shl(unsigned shiftAmt) const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const { assert(shiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (shiftAmt >= BitWidth) @@ -778,65 +863,74 @@ public: return shlSlowCase(shiftAmt); } - /// @brief Rotate left by rotateAmt. - APInt rotl(unsigned rotateAmt) const; + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const; - /// @brief Rotate right by rotateAmt. - APInt rotr(unsigned rotateAmt) const; + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const; + /// \brief Arithmetic right-shift function. + /// /// Arithmetic right-shift this APInt by shiftAmt. - /// @brief Arithmetic right-shift function. - APInt ashr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const; + /// \brief Logical right-shift function. + /// /// Logical right-shift this APInt by shiftAmt. - /// @brief Logical right-shift function. - APInt lshr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const; + /// \brief Left-shift function. + /// /// Left-shift this APInt by shiftAmt. - /// @brief Left-shift function. - APInt shl(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const; - /// @brief Rotate left by rotateAmt. - APInt rotl(const APInt &rotateAmt) const; + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const; - /// @brief Rotate right by rotateAmt. - APInt rotr(const APInt &rotateAmt) const; + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const; + /// \brief Unsigned division operation. + /// /// 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; + /// + /// \returns a new APInt value containing the division result + APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const; + /// \brief Signed division function for APInt. + /// /// Signed divide this APInt by APInt RHS. - /// @brief Signed division function for APInt. - APInt sdiv(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const; + /// \brief Unsigned remainder operation. + /// /// 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; + /// 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 + APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const; + /// \brief Function for signed remainder operation. + /// /// Signed remainder operation on APInt. - /// @brief Function for signed remainder operation. - APInt srem(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const; + /// \brief Dual division/remainder interface. + /// /// 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); + 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); // Operations that return overflow indicators. APInt sadd_ov(const APInt &RHS, bool &Overflow) const; @@ -848,247 +942,261 @@ public: APInt umul_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. + /// \brief Array-indexing support. + /// + /// \returns the bit value at bitPosition bool operator[](unsigned bitPosition) const { assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); return (maskBit(bitPosition) & - (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != + 0; } /// @} - /// @name Comparison Operators + /// \name Comparison Operators /// @{ + + /// \brief Equality operator. + /// /// Compares this APInt with RHS for the validity of the equality /// relationship. - /// @brief Equality operator. - bool operator==(const APInt& RHS) const { + bool operator==(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); if (isSingleWord()) return VAL == RHS.VAL; return EqualSlowCase(RHS); } + /// \brief Equality operator. + /// /// Compares this APInt with a uint64_t for the validity of the equality /// relationship. - /// @returns true if *this == Val - /// @brief Equality operator. + /// + /// \returns true if *this == Val bool operator==(uint64_t Val) const { if (isSingleWord()) return VAL == Val; return EqualSlowCase(Val); } + /// \brief Equality comparison. + /// /// 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; - } + /// + /// \returns true if *this == Val + bool eq(const APInt &RHS) const { return (*this) == RHS; } + /// \brief Inequality operator. + /// /// 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); - } + /// + /// \returns true if *this != Val + bool operator!=(const APInt &RHS) const { return !((*this) == RHS); } + /// \brief Inequality operator. + /// /// 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); - } + /// + /// \returns true if *this != Val + bool operator!=(uint64_t Val) const { return !((*this) == Val); } + /// \brief Inequality comparison + /// /// 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); - } + /// + /// \returns true if *this != Val + bool ne(const APInt &RHS) const { return !((*this) == RHS); } + /// \brief Unsigned less than comparison + /// /// 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 + /// + /// \returns true if *this < RHS when both are considered unsigned. bool ult(const APInt &RHS) const; + /// \brief Unsigned less than comparison + /// /// 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)); - } + /// + /// \returns true if *this < RHS when considered unsigned. + bool ult(uint64_t RHS) const { return ult(APInt(getBitWidth(), RHS)); } + /// \brief Signed less than comparison + /// /// 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; + /// + /// \returns true if *this < RHS when both are considered signed. + bool slt(const APInt &RHS) const; + /// \brief Signed less than comparison + /// /// 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)); - } + /// + /// \returns true if *this < RHS when considered signed. + bool slt(uint64_t RHS) const { return slt(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned less or equal comparison + /// /// 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); - } + /// + /// \returns true if *this <= RHS when both are considered unsigned. + bool ule(const APInt &RHS) const { return ult(RHS) || eq(RHS); } + /// \brief Unsigned less or equal comparison + /// /// 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)); - } + /// + /// \returns true if *this <= RHS when considered unsigned. + bool ule(uint64_t RHS) const { return ule(APInt(getBitWidth(), RHS)); } + /// \brief Signed less or equal comparison + /// /// 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); - } + /// + /// \returns true if *this <= RHS when both are considered signed. + 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)); - } + /// \brief Signed less or equal comparison + /// + /// 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. + bool sle(uint64_t RHS) const { return sle(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned greather than comparison + /// /// 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); - } + /// + /// \returns true if *this > RHS when both are considered unsigned. + bool ugt(const APInt &RHS) const { return !ult(RHS) && !eq(RHS); } + /// \brief Unsigned greater than comparison + /// /// 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)); - } + /// + /// \returns true if *this > RHS when considered unsigned. + 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); - } + /// \brief Signed greather than comparison + /// + /// 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. + bool sgt(const APInt &RHS) const { return !slt(RHS) && !eq(RHS); } + /// \brief Signed greater than comparison + /// /// 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)); - } + /// + /// \returns true if *this > RHS when considered signed. + bool sgt(uint64_t RHS) const { return sgt(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned greater or equal comparison + /// /// 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); - } + /// + /// \returns true if *this >= RHS when both are considered unsigned. + bool uge(const APInt &RHS) const { return !ult(RHS); } + /// \brief Unsigned greater or equal comparison + /// /// 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)); - } + /// + /// \returns true if *this >= RHS when considered unsigned. + bool uge(uint64_t RHS) const { return uge(APInt(getBitWidth(), RHS)); } + /// \brief Signed greather or equal comparison + /// /// 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); - } + /// + /// \returns true if *this >= RHS when both are considered signed. + bool sge(const APInt &RHS) const { return !slt(RHS); } + /// \brief Signed greater or equal comparison + /// /// 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)); - } + /// + /// \returns true if *this >= RHS when considered signed. + 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; - } + bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; } /// @} - /// @name Resizing Operators + /// \name Resizing Operators /// @{ + + /// \brief Truncate to new width. + /// /// 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; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const; + /// \brief Sign extend to a new width. + /// /// 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; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const; + /// \brief Zero extend to a new width. + /// /// 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; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const; + /// \brief Sign extend or truncate to width + /// /// 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; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const; + /// \brief Zero extend or truncate to width + /// /// 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; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const; + /// \brief Sign extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, or left alone to make it that width. - /// @brief Sign extend or truncate to width - APInt sextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const; + /// \brief Zero extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, or left alone to make it that width. - /// @brief Zero extend or truncate to width - APInt zextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const; /// @} - /// @name Bit Manipulation Operators + /// \name Bit Manipulation Operators /// @{ - /// @brief Set every bit to 1. + + /// \brief Set every bit to 1. void setAllBits() { if (isSingleWord()) VAL = UINT64_MAX; @@ -1101,11 +1209,12 @@ public: clearUnusedBits(); } + /// \brief Set a given bit to 1. + /// /// 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. + /// \brief Set every bit to 0. void clearAllBits() { if (isSingleWord()) VAL = 0; @@ -1113,11 +1222,12 @@ public: memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); } + /// \brief Set a given bit to 0. + /// /// 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. + /// \brief Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) VAL ^= UINT64_MAX; @@ -1128,68 +1238,71 @@ public: clearUnusedBits(); } + /// \brief Toggles a given 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 flipBit(unsigned bitPosition); /// @} - /// @name Value Characterization Functions + /// \name Value Characterization Functions /// @{ - /// @returns the total number of bits. - unsigned getBitWidth() const { - return BitWidth; - } + /// \brief Return the number of bits in the APInt. + unsigned getBitWidth() const { return BitWidth; } + /// \brief Get the number of words. + /// /// 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); - } + /// + /// \returns the number of words to hold the integer value of this APInt. + 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. + /// \brief Get the number of words. + /// + /// *NOTE* 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. static unsigned getNumWords(unsigned BitWidth) { return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; } + /// \brief Compute the number of active bits in the value + /// /// 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(); - } + 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. + /// \brief Compute 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 { unsigned numActiveBits = getActiveBits(); return numActiveBits ? whichWord(numActiveBits - 1) + 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 + /// \brief Get the minimum bit size for this signed APInt + /// + /// 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; + return getActiveBits() + 1; } + /// \brief Get zero extended value + /// /// 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; @@ -1197,43 +1310,49 @@ public: return pVal[0]; } + /// \brief Get sign extended value + /// /// 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); + (APINT_BITS_PER_WORD - BitWidth); assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); return int64_t(pVal[0]); } + /// \brief Get bits required for string value. + /// /// This method determines how many bits are required to hold the APInt /// equivalent of the string given by \p 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, otherwise - /// returns the number of zeros from the most significant bit to the first - /// one bits. + /// \brief The APInt version of the countLeadingZeros 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, otherwise 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 llvm::countLeadingZeros(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, otherwise - /// returns the number of 1 bits from the most significant to the least - /// @brief Count the number of leading one bits. + /// \brief Count the number of leading one bits. + /// + /// 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, otherwise returns the number + /// of 1 bits from the most significant to the least unsigned countLeadingOnes() const; /// Computes the number of leading bits of this APInt that are equal to its @@ -1242,34 +1361,36 @@ public: 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, otherwise - /// returns the number of zeros from the least significant bit to the first - /// one bit. - /// @brief Count the number of trailing zero bits. + /// \brief Count the number of trailing zero bits. + /// + /// 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, otherwise returns the number of + /// zeros from the least significant bit to the first one bit. 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, otherwise - /// returns the number of ones from the least significant bit to the first - /// zero bit. - /// @brief Count the number of trailing one bits. + /// \brief Count the number of trailing one bits. + /// + /// 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, otherwise returns the number + /// of ones from the least significant bit to the first zero bit. 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, otherwise returns the number of set - /// bits. - /// @brief Count the number of bits set. + /// \brief Count the number of bits set. + /// + /// 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, otherwise returns the number of set bits. unsigned countPopulation() const { if (isSingleWord()) return CountPopulation_64(VAL); @@ -1277,12 +1398,12 @@ public: } /// @} - /// @name Conversion Functions + /// \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. + /// Converts an APInt to a string and append it to Str. Str is commonly a + /// SmallString. void toString(SmallVectorImpl &Str, unsigned Radix, bool Signed, bool formatAsCLiteral = false) const; @@ -1298,32 +1419,30 @@ public: toString(Str, Radix, true, false); } - /// 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. + /// \brief Return 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 LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const; - /// @returns a byte-swapped representation of this APInt Value. - APInt byteSwap() const; - - /// @brief Converts this APInt to a double value. + /// \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 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); - } + /// \brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { return roundToDouble(true); } + /// \brief Converts APInt bits to a double + /// /// 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; @@ -1333,10 +1452,11 @@ public: return T.D; } + /// \brief Converts APInt bits to a double + /// /// 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; @@ -1346,10 +1466,11 @@ public: return T.F; } + /// \brief Converts a double to APInt bits. + /// /// 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) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) { union { uint64_t I; double D; @@ -1358,10 +1479,11 @@ public: return APInt(sizeof T * CHAR_BIT, T.I); } + /// \brief Converts a float to APInt bits. + /// /// 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) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) { union { unsigned I; float F; @@ -1371,20 +1493,18 @@ public: } /// @} - /// @name Mathematics Operations + /// \name Mathematics Operations /// @{ - /// @returns the floor log base 2 of this APInt. - unsigned logBase2() const { - return BitWidth - 1 - countLeadingZeros(); - } + /// \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. + /// \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 + /// \returns the log base 2 of this APInt if its an exact power of two, -1 /// otherwise int32_t exactLogBase2() const { if (!isPowerOf2()) @@ -1392,22 +1512,23 @@ public: return logBase2(); } - /// @brief Compute the square root - APInt sqrt() const; + /// \brief Compute the square root + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const; + /// \brief Get the absolute value; + /// /// If *this is < 0 then return -(*this), otherwise *this; - /// @brief Get the absolute value; - APInt abs() const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const { if (isNegative()) return -(*this); return *this; } - /// @returns the multiplicative inverse for a given modulo. - APInt multiplicativeInverse(const APInt& modulo) const; + /// \returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt &modulo) const; /// @} - /// @name Support for division by constant + /// \name Support for division by constant /// @{ /// Calculate the magic number for signed division by a constant. @@ -1419,18 +1540,17 @@ public: mu magicu(unsigned LeadingZeros = 0) const; /// @} - /// @name Building-block Operations for APInt and APFloat + /// \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. + // 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. */ + /// 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. @@ -1442,13 +1562,13 @@ public: /// 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. + /// 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); + const integerPart *, unsigned int srcBits, + unsigned int srcLSB); /// Set the given bit of a bignum. Zero-based. static void tcSetBit(integerPart *, unsigned int bit); @@ -1456,76 +1576,70 @@ public: /// 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. + /// 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. + /// 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. + /// 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 + /// 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. + /// 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. + /// 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. + /// 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. + /// 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. + /// 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. + /// 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. + /// 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); @@ -1536,17 +1650,19 @@ public: static void tcComplement(integerPart *, unsigned int); /// Comparison (unsigned) of two bignums. - static int tcCompare(const integerPart *, const integerPart *, - unsigned int); + static int tcCompare(const integerPart *, const integerPart *, unsigned int); /// Increment a bignum in-place. Return the carry flag. static integerPart tcIncrement(integerPart *, unsigned int); + /// Decrement a bignum in-place. Return the borrow flag. + static integerPart tcDecrement(integerPart *, unsigned int); + /// Set the least significant BITS and clear the rest. static void tcSetLeastSignificantBits(integerPart *, unsigned int, unsigned int bits); - /// @brief debug method + /// \brief debug method void dump() const; /// @} @@ -1554,24 +1670,20 @@ public: /// Magic data for optimising signed division by a constant. struct APInt::ms { - APInt m; ///< magic number - unsigned s; ///< shift amount + 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 + 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 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); @@ -1580,188 +1692,173 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { 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 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 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 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 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 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) { +/// \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) { +/// \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); + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); } -/// @returns true if the argument APInt value contains a sequence of ones +/// \brief Return 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); +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(); -} +/// \brief 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(); -} +/// \brief 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); +/// \brief Compute GCD of two APInt values. +/// +/// 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 +APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2); +/// \brief Converts the given APInt to a double value. +/// /// 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) { +inline double RoundAPIntToDouble(const APInt &APIVal) { return APIVal.roundToDouble(); } +/// \brief Converts the given APInt to a double value. +/// /// 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) { +inline double RoundSignedAPIntToDouble(const APInt &APIVal) { return APIVal.signedRoundToDouble(); } -/// @brief Converts the given APInt to a float vlalue. -inline float RoundAPIntToFloat(const APInt& APIVal) { +/// \brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt &APIVal) { return float(RoundAPIntToDouble(APIVal)); } +/// \brief Converts the given APInt to a float value. +/// /// 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) { +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. +/// \brief Converts the given double value into a APInt. +/// +/// This function convert a double value to an APInt value. APInt RoundDoubleToAPInt(double Double, unsigned width); -/// RoundFloatToAPInt - Converts a float value into an APInt value. -/// @brief Converts a float value into a APInt. +/// \brief Converts a float value into a APInt. +/// +/// Converts a float value into an APInt value. inline APInt RoundFloatToAPInt(float Float, unsigned width) { return RoundDoubleToAPInt(double(Float), width); } +/// \brief Arithmetic right-shift function. +/// /// Arithmetic right-shift the APInt by shiftAmt. -/// @brief Arithmetic right-shift function. -inline APInt ashr(const APInt& LHS, unsigned shiftAmt) { +inline APInt ashr(const APInt &LHS, unsigned shiftAmt) { return LHS.ashr(shiftAmt); } +/// \brief Logical right-shift function. +/// /// Logical right-shift the APInt by shiftAmt. -/// @brief Logical right-shift function. -inline APInt lshr(const APInt& LHS, unsigned shiftAmt) { +inline APInt lshr(const APInt &LHS, unsigned shiftAmt) { return LHS.lshr(shiftAmt); } +/// \brief Left-shift function. +/// /// Left-shift the APInt by shiftAmt. -/// @brief Left-shift function. -inline APInt shl(const APInt& LHS, unsigned shiftAmt) { +inline APInt shl(const APInt &LHS, unsigned shiftAmt) { return LHS.shl(shiftAmt); } +/// \brief Signed division function for APInt. +/// /// 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); -} +inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); } +/// \brief Unsigned division function for APInt. +/// /// 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); -} +inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); } +/// \brief Function for signed remainder operation. +/// /// Signed remainder operation on APInt. -/// @brief Function for signed remainder operation. -inline APInt srem(const APInt& LHS, const APInt& RHS) { - return LHS.srem(RHS); -} +inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); } +/// \brief Function for unsigned remainder operation. +/// /// Unsigned remainder operation on APInt. -/// @brief Function for unsigned remainder operation. -inline APInt urem(const APInt& LHS, const APInt& RHS) { - return LHS.urem(RHS); -} +inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); } +/// \brief Function for multiplication operation. +/// /// Performs multiplication on APInt values. -/// @brief Function for multiplication operation. -inline APInt mul(const APInt& LHS, const APInt& RHS) { - return LHS * RHS; -} +inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; } +/// \brief Function for addition operation. +/// /// Performs addition on APInt values. -/// @brief Function for addition operation. -inline APInt add(const APInt& LHS, const APInt& RHS) { - return LHS + RHS; -} +inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; } +/// \brief Function for subtraction operation. +/// /// Performs subtraction on APInt values. -/// @brief Function for subtraction operation. -inline APInt sub(const APInt& LHS, const APInt& RHS) { - return LHS - RHS; -} +inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; } +/// \brief Bitwise AND function for APInt. +/// /// 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; -} +inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; } +/// \brief Bitwise OR function for APInt. +/// /// 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; -} +inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; } +/// \brief Bitwise XOR function for APInt. +/// /// Performs bitwise XOR operation on APInt. -/// @brief Bitwise XOR function for APInt. -inline APInt Xor(const APInt& LHS, const APInt& RHS) { - return LHS ^ RHS; -} +inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; } +/// \brief Bitwise complement function. +/// /// Performs a bitwise complement operation on APInt. -/// @brief Bitwise complement function. -inline APInt Not(const APInt& APIVal) { - return ~APIVal; -} +inline APInt Not(const APInt &APIVal) { return ~APIVal; } } // End of APIntOps namespace - // See friend declaration above. This additional declaration is required in - // order to compile LLVM with IBM xlC compiler. - hash_code hash_value(const APInt &Arg); +// See friend declaration above. This additional declaration is required in +// order to compile LLVM with IBM xlC compiler. +hash_code hash_value(const APInt &Arg); } // End of llvm namespace #endif diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 11be4c513e2c3..ad035a7c30df4 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -68,18 +68,18 @@ public: } using APInt::toString; - APSInt trunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } - APSInt extend(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { if (IsUnsigned) return APSInt(zext(width), IsUnsigned); else return APSInt(sext(width), IsUnsigned); } - APSInt extOrTrunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { if (IsUnsigned) return APSInt(zextOrTrunc(width), IsUnsigned); else @@ -212,7 +212,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) & RHS, IsUnsigned); } - APSInt And(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { return this->operator&(RHS); } @@ -220,7 +220,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) | RHS, IsUnsigned); } - APSInt Or(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { return this->operator|(RHS); } @@ -229,7 +229,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) ^ RHS, IsUnsigned); } - APSInt Xor(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { return this->operator^(RHS); } diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index d4152ec727b13..e5562c3683098 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -80,9 +80,16 @@ namespace llvm { /// Construct an ArrayRef from a C array. template - /*implicit*/ ArrayRef(const T (&Arr)[N]) + /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} +#if LLVM_HAS_INITIALIZER_LISTS + /// Construct an ArrayRef from a std::initializer_list. + /*implicit*/ ArrayRef(const std::initializer_list &Vec) + : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), + Length(Vec.size()) {} +#endif + /// @} /// @name Simple Operations /// @{ @@ -178,6 +185,8 @@ namespace llvm { public: typedef T *iterator; + typedef std::reverse_iterator reverse_iterator; + /// Construct an empty MutableArrayRef. /*implicit*/ MutableArrayRef() : ArrayRef() {} @@ -212,6 +221,9 @@ namespace llvm { iterator begin() const { return data(); } iterator end() const { return data() + this->size(); } + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + /// front - Get the first element. T &front() const { assert(!this->empty()); diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 82cfdf437d4e7..8fb538f68fcf5 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -138,8 +138,15 @@ public: /// all - Returns true if all bits are set. bool all() const { - // TODO: Optimize this. - return count() == size(); + for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i) + if (Bits[i] != ~0UL) + return false; + + // If bits remain check that they are ones. The unused bits are always zero. + if (unsigned Remainder = Size % BITWORD_SIZE) + return Bits[Size / BITWORD_SIZE] == (1UL << Remainder) - 1; + + return true; } /// none - Returns true if none of the bits are set. @@ -153,9 +160,9 @@ public: 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]); + return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; @@ -176,9 +183,9 @@ public: if (Copy != 0) { if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy); if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); llvm_unreachable("Unsupported!"); } @@ -186,9 +193,9 @@ public: 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]); + return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 31fd6d899daec..ce322cce4e0b4 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -64,7 +64,9 @@ public: return const_iterator(getBucketsEnd(), getBucketsEnd(), true); } - bool empty() const { return getNumEntries() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return getNumEntries() == 0; + } unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink @@ -222,11 +224,11 @@ public: if (LookupBucketFor(Key, TheBucket)) return *TheBucket; - return *InsertIntoBucket(Key, ValueT(), TheBucket); + return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket); } ValueT &operator[](KeyT &&Key) { - return FindAndConstruct(Key).second; + return FindAndConstruct(std::move(Key)).second; } #endif @@ -436,9 +438,8 @@ private: this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } - if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { - this->grow(NumBuckets * 2); + } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } assert(TheBucket); @@ -713,13 +714,13 @@ public: init(NumInitBuckets); } - SmallDenseMap(const SmallDenseMap &other) { + SmallDenseMap(const SmallDenseMap &other) : BaseT() { init(0); copyFrom(other); } #if LLVM_HAS_RVALUE_REFERENCES - SmallDenseMap(SmallDenseMap &&other) { + SmallDenseMap(SmallDenseMap &&other) : BaseT() { init(0); swap(other); } diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 91794dea69819..1b2c94c35f84e 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -352,7 +352,8 @@ template class FoldingSetBucketIterator; template inline bool DefaultFoldingSetTrait::Equals(T &X, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) { + unsigned /*IDHash*/, + FoldingSetNodeID &TempID) { FoldingSetTrait::Profile(X, TempID); return TempID == ID; } @@ -366,7 +367,7 @@ template inline bool DefaultContextualFoldingSetTrait::Equals(T &X, const FoldingSetNodeID &ID, - unsigned IDHash, + unsigned /*IDHash*/, FoldingSetNodeID &TempID, Ctx Context) { ContextualFoldingSetTrait::Profile(X, TempID, Context); diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index a667479a4d176..8f8fb98770405 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -211,6 +211,7 @@ public: friend class ImmutableMap; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableMap::value_type value_type; typedef typename ImmutableMap::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index fbdf066e61ab6..ad349699e2a11 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -851,6 +851,18 @@ PROFILE_INTEGER_INFO(unsigned long long) #undef PROFILE_INTEGER_INFO +/// Profile traits for booleans. +template <> +struct ImutProfileInfo { + typedef const bool value_type; + typedef const bool& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddBoolean(X); + } +}; + + /// Generic profile trait for pointer types. We treat pointers as /// references to unique objects. template @@ -1060,6 +1072,7 @@ public: friend class ImmutableSet; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableSet::value_type value_type; typedef typename ImmutableSet::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index c4083eed6a993..1ca3288a350ab 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -496,7 +496,7 @@ public: NodeRef() {} /// operator bool - Detect a null ref. - operator bool() const { return pip.getOpaqueValue(); } + LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } /// NodeRef - Create a reference to the node p with n elements. template @@ -612,7 +612,7 @@ public: /// 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 Pos Starting index = insertFrom(0, size, a) /// @param Size Number of elements in node. /// @param a Interval start. /// @param b Interval stop. @@ -1956,7 +1956,7 @@ iterator::eraseNode(unsigned Level) { /// 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). +/// @tparam 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 diff --git a/include/llvm/ADT/NullablePtr.h b/include/llvm/ADT/NullablePtr.h deleted file mode 100644 index 8ddfd5d20abdc..0000000000000 --- a/include/llvm/ADT/NullablePtr.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- 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_NULLABLEPTR_H -#define LLVM_ADT_NULLABLEPTR_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/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h index 86f9feee2cb4c..6b9e42eaec0f1 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -70,8 +70,9 @@ public: T *operator->() const { return Ptr; } T *get() const { return Ptr; } - operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != 0; } bool operator!() const { return Ptr == 0; } + bool isValid() const { return Ptr != 0; } void swap(OwningPtr &RHS) { T *Tmp = RHS.Ptr; @@ -132,7 +133,7 @@ public: } T *get() const { return Ptr; } - operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != 0; } bool operator!() const { return Ptr == 0; } void swap(OwningArrayPtr &RHS) { diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 0299a83c4411c..0cfd470003af7 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_POINTERINTPAIR_H #define LLVM_ADT_POINTERINTPAIR_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include @@ -40,7 +41,7 @@ template > class PointerIntPair { intptr_t Value; - enum { + enum LLVM_ENUM_INT_TYPE(uintptr_t) { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index f42515ac77a74..05d362feab22b 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -15,6 +15,7 @@ #ifndef LLVM_ADT_POINTERUNION_H #define LLVM_ADT_POINTERUNION_H +#include "llvm/Support/Compiler.h" #include "llvm/ADT/PointerIntPair.h" namespace llvm { @@ -71,7 +72,7 @@ namespace llvm { /// 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) + /// Z = P.get(); // compile time failure. /// P = (float*)0; /// Y = P.get(); // ok. /// X = P.get(); // runtime assertion failure. @@ -109,7 +110,7 @@ namespace llvm { // we recursively strip off low bits if we have a nested PointerUnion. return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - operator bool() const { return !isNull(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -174,7 +175,19 @@ namespace llvm { return V; } }; - + + template + static bool operator==(PointerUnion lhs, + PointerUnion rhs) { + return lhs.getOpaqueValue() == rhs.getOpaqueValue(); + } + + template + static bool operator!=(PointerUnion lhs, + PointerUnion rhs) { + return lhs.getOpaqueValue() != rhs.getOpaqueValue(); + } + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits)-1. template @@ -251,7 +264,7 @@ namespace llvm { /// 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(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -359,7 +372,7 @@ namespace llvm { /// 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(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index dacda36521290..3aa8183353215 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -217,6 +217,22 @@ inline tier tie(T1& f, T2& s) { return tier(f, s); } +/// \brief Function object to check whether the first component of a std::pair +/// compares less than the first component of another std::pair. +struct less_first { + template bool operator()(const T &lhs, const T &rhs) const { + return lhs.first < rhs.first; + } +}; + +/// \brief Function object to check whether the second component of a std::pair +/// compares less than the second component of another std::pair. +struct less_second { + template bool operator()(const T &lhs, const T &rhs) const { + return lhs.second < rhs.second; + } +}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -277,12 +293,16 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) { get_array_pod_sort_comparator(*Start)); } -template -inline void array_pod_sort(IteratorTy Start, IteratorTy End, - int (*Compare)(const void*, const void*)) { +template +inline void array_pod_sort( + IteratorTy Start, IteratorTy End, + int (*Compare)( + const typename std::iterator_traits::value_type *, + const typename std::iterator_traits::value_type *)) { // Don't dereference start iterator of empty sequence. if (Start == End) return; - qsort(&*Start, End-Start, sizeof(*Start), Compare); + qsort(&*Start, End - Start, sizeof(*Start), + reinterpret_cast(Compare)); } //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index d2f7286c2596d..5eda37c675fee 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -170,7 +170,7 @@ public: vector_.pop_back(); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { T Ret = back(); pop_back(); return Ret; diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 652492a1538cb..86949b2ae3420 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -216,9 +216,9 @@ public: if (Bits == 0) return -1; if (NumBaseBits == 32) - return CountTrailingZeros_32(Bits); + return countTrailingZeros(Bits); if (NumBaseBits == 64) - return CountTrailingZeros_64(Bits); + return countTrailingZeros(Bits); llvm_unreachable("Unsupported!"); } return getPointer()->find_first(); @@ -234,9 +234,9 @@ public: if (Bits == 0 || Prev + 1 >= getSmallSize()) return -1; if (NumBaseBits == 32) - return CountTrailingZeros_32(Bits); + return countTrailingZeros(Bits); if (NumBaseBits == 64) - return CountTrailingZeros_64(Bits); + return countTrailingZeros(Bits); llvm_unreachable("Unsupported!"); } return getPointer()->find_next(Prev); @@ -426,6 +426,40 @@ public: return *this; } + /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. + SmallBitVector &reset(const SmallBitVector &RHS) { + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() & ~RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->reset(*RHS.getPointer()); + else + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (RHS.test(i)) + reset(i); + + return *this; + } + + /// test - Check if (This - RHS) is zero. + /// This is the same as reset(RHS) and any(). + bool test(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & ~RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->test(*RHS.getPointer()); + + unsigned i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && !RHS.test(i)) + return true; + + for (e = size(); i != e; ++i) + if (test(i)) + return true; + + return false; + } + SmallBitVector &operator|=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); if (isSmall()) diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 8c7304197f34f..bd0d8838ef02b 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -71,7 +71,7 @@ protected: ~SmallPtrSetImpl(); public: - bool empty() const { return size() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } unsigned size() const { return NumElements; } void clear() { diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 7ba0a714bfc76..505aa8d8ae618 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -53,7 +53,7 @@ public: return size_t((char*)CapacityX - (char*)BeginX); } - bool empty() const { return BeginX == EndX; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } }; template struct SmallVectorStorage; @@ -427,7 +427,7 @@ public: this->grow(N); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { #if LLVM_HAS_RVALUE_REFERENCES T Result = ::std::move(this->back()); #else diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 306e92832f0b0..7a10f857044d6 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -137,9 +137,9 @@ public: 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]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } llvm_unreachable("Illegal empty element"); @@ -162,9 +162,9 @@ public: if (Copy != 0) { if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); llvm_unreachable("Unsupported!"); } @@ -172,9 +172,9 @@ public: 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]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index d2887c5c2c56f..56dbb5b806899 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H +#include #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" @@ -159,6 +160,48 @@ static inline StringRef getOrdinalSuffix(unsigned Val) { } } +template +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::input_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +/// Joins the strings in the range [Begin, End), adding Separator between +/// the elements. +template +inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { + typedef typename std::iterator_traits::iterator_category tag; + return join_impl(Begin, End, Separator, tag()); +} + } // End llvm namespace #endif diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index d01437b61c2bb..0838ebe91f1ba 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -102,6 +102,13 @@ public: bool empty() const { return NumItems == 0; } unsigned size() const { return NumItems; } + + void swap(StringMapImpl &Other) { + std::swap(TheTable, Other.TheTable); + std::swap(NumBuckets, Other.NumBuckets); + std::swap(NumItems, Other.NumItems); + std::swap(NumTombstones, Other.NumTombstones); + } }; /// StringMapEntry - This is used to represent one value that is inserted into @@ -109,6 +116,7 @@ public: /// and data. template class StringMapEntry : public StringMapEntryBase { + StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; public: ValueTy second; @@ -409,6 +417,8 @@ protected: public: typedef StringMapEntry value_type; + StringMapConstIterator() : Ptr(0) { } + explicit StringMapConstIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) : Ptr(Bucket) { @@ -448,6 +458,7 @@ private: template class StringMapIterator : public StringMapConstIterator { public: + StringMapIterator() {} explicit StringMapIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) : StringMapConstIterator(Bucket, NoAdvance) { diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index d013d05623252..ec0c2849f37ef 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -19,7 +19,7 @@ #include namespace llvm { - template + template class SmallVectorImpl; class APInt; class hash_code; @@ -175,7 +175,7 @@ namespace llvm { /// 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); + unsigned MaxEditDistance = 0) const; /// str - Get the contents as an std::string. std::string str() const { @@ -210,12 +210,18 @@ namespace llvm { compareMemory(Data, Prefix.Data, Prefix.Length) == 0; } + /// Check if this string starts with the given \p Prefix, ignoring case. + bool startswith_lower(StringRef Prefix) const; + /// Check if this string ends with the given \p Suffix. bool endswith(StringRef Suffix) const { return Length >= Suffix.Length && compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; } + /// Check if this string ends with the given \p Suffix, ignoring case. + bool endswith_lower(StringRef Suffix) const; + /// @} /// @name String Searching /// @{ @@ -548,6 +554,10 @@ namespace llvm { template struct isPodLike; template <> struct isPodLike { static const bool value = true; }; + /// Construct a string ref from a boolean. + inline StringRef toStringRef(bool B) { + return StringRef(B ? "true" : "false"); + } } #endif diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 3a72e8704f61d..84e0b29d1fe06 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -14,30 +14,33 @@ // Some system headers or GCC predefined macros conflict with identifiers in // this file. Undefine them here. +#undef NetBSD #undef mips #undef sparc namespace llvm { -/// Triple - Helper class for working with target triples. +/// Triple - Helper class for working with autoconf configuration names. For +/// historical reasons, we also call these 'triples' (they used to contain +/// exactly three fields). /// -/// Target triples are strings in the canonical form: +/// Configuration names 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. +/// configuration names, but also want to implement certain special +/// behavior for particular configurations. This class isolates the mapping +/// from the components of the configuration name 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. +/// See autoconf/config.guess for a glimpse into what configuration names +/// look like in practice. class Triple { public: enum ArchType { @@ -53,6 +56,7 @@ public: msp430, // MSP430: msp430 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 @@ -62,7 +66,6 @@ public: x86, // X86: i[3-9]86 x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore - mblaze, // MBlaze: mblaze nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) @@ -79,7 +82,8 @@ public: BGP, BGQ, Freescale, - IBM + IBM, + NVIDIA }; enum OSType { UnknownOS, @@ -105,7 +109,9 @@ public: NaCl, // Native Client CNK, // BG/P Compute-Node Kernel Bitrig, - AIX + AIX, + CUDA, // NVIDIA CUDA + NVCL // NVIDIA OpenCL }; enum EnvironmentType { UnknownEnvironment, @@ -313,7 +319,12 @@ public: return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32; } - /// isOSWindows - Is this a "Windows" OS. + /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + bool isOSMSVCRT() const { + return getOS() == Triple::Win32 || getOS() == Triple::MinGW32; + } + + /// \brief Tests whether the OS is Windows. bool isOSWindows() const { return getOS() == Triple::Win32 || isOSCygMing(); } @@ -323,6 +334,11 @@ public: return getOS() == Triple::NaCl; } + /// \brief Tests whether the OS is Linux. + bool isOSLinux() const { + return getOS() == Triple::Linux; + } + /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { return !isOSDarwin() && !isOSWindows(); diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 71dab2ef551c7..6aeaa91f1b167 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -382,7 +382,9 @@ public: // Miscellaneous inspection routines. size_type max_size() const { return size_type(-1); } - bool empty() const { return Head == 0 || Head == getTail(); } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return Head == 0 || Head == getTail(); + } // Front and back accessor functions... reference front() { @@ -534,7 +536,7 @@ public: // Functionality derived from other functions defined above... // - size_type size() const { + size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { if (Head == 0) return 0; // Don't require construction of sentinel if empty. return std::distance(begin(), end()); } diff --git a/include/llvm/ADT/polymorphic_ptr.h b/include/llvm/ADT/polymorphic_ptr.h new file mode 100644 index 0000000000000..b8d8d71238e3c --- /dev/null +++ b/include/llvm/ADT/polymorphic_ptr.h @@ -0,0 +1,117 @@ +//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- 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 provides a polymorphic_ptr class template. See the class comments +/// for details about this API, its intended use cases, etc. +/// +/// The primary motivation here is to work around the necessity of copy +/// semantics in C++98. This is typically used where any actual copies are +/// incidental or unnecessary. As a consequence, it is expected to cease to be +/// useful and be removed when we can directly rely on move-only types. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POLYMORPHIC_PTR_H +#define LLVM_ADT_POLYMORPHIC_PTR_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +/// \brief An owning, copyable polymorphic smart pointer. +/// +/// This pointer exists to provide copyable owned smart pointer. Rather than +/// shared ownership semantics, it has unique ownership semantics and deep copy +/// semantics. It is copyable by requiring that the underlying type exposes +/// a method which can produce a (heap allocated) clone. +/// +/// Note that in almost all scenarios use of this could be avoided if we could +/// build move-only containers of a std::unique_ptr, but until then this +/// provides an effective way to place polymorphic objects in a container. +template class polymorphic_ptr { + T *ptr; + +public: + polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} + polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} +#if LLVM_HAS_RVALUE_REFERENCES + polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} +#endif + ~polymorphic_ptr() { delete ptr; } + + polymorphic_ptr &operator=(polymorphic_ptr arg) { + swap(arg); + return *this; + } + polymorphic_ptr &operator=(T *arg) { + if (arg != ptr) { + delete ptr; + ptr = arg; + } + return *this; + } + + T &operator*() const { return *ptr; } + T *operator->() const { return ptr; } + LLVM_EXPLICIT operator bool() const { return ptr != 0; } + bool operator!() const { return ptr == 0; } + + T *get() const { return ptr; } + + T *take() { + T *tmp = ptr; + ptr = 0; + return tmp; + } + + void swap(polymorphic_ptr &arg) { + T *tmp = ptr; + ptr = arg.ptr; + arg.ptr = tmp; + } +}; + +template +void swap(polymorphic_ptr &lhs, polymorphic_ptr &rhs) { + lhs.swap(rhs); +} + +template +bool operator==(const polymorphic_ptr &lhs, const polymorphic_ptr &rhs) { + return lhs.get() == rhs.get(); +} + +template +bool operator!=(const polymorphic_ptr &lhs, const polymorphic_ptr &rhs) { + return lhs.get() != rhs.get(); +} + +template +bool operator==(const polymorphic_ptr &lhs, U *rhs) { + return lhs.get() == rhs; +} + +template +bool operator!=(const polymorphic_ptr &lhs, U *rhs) { + return lhs.get() != rhs; +} + +template +bool operator==(T *lhs, const polymorphic_ptr &rhs) { + return lhs == rhs.get(); +} + +template +bool operator!=(T *lhs, const polymorphic_ptr &rhs) { + return lhs != rhs.get(); +} + +} + +#endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index d703f21c021c6..efafbbdb77613 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -584,6 +584,10 @@ struct DenseMapInfo { /// function. bool isNoAliasCall(const Value *V); +/// isNoAliasArgument - Return true if this is an argument with the noalias +/// attribute. +bool isNoAliasArgument(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) diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index b3e2d18eb2c6e..817a44188b894 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -1,4 +1,4 @@ -//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===// +//===-- BlockFrequencyImpl.h - Block Frequency Implementation --*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -33,7 +33,7 @@ class BlockFrequencyInfo; class MachineBlockFrequencyInfo; /// BlockFrequencyImpl implements block frequency algorithm for IR and -/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) +/// Machine Instructions. Algorithm starts with value ENTRY_FREQ /// for the entry block and then propagates frequencies using branch weights /// from (Machine)BranchProbabilityInfo. LoopInfo is not required because /// algorithm can find "backedges" by itself. @@ -85,31 +85,16 @@ class BlockFrequencyImpl { << " --> " << Freqs[BB] << "\n"); } - /// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing. - /// - void divBlockFreq(BlockT *BB, BranchProbability Prob) { - uint64_t N = Prob.getNumerator(); - assert(N && "Illegal division by zero!"); - uint64_t D = Prob.getDenominator(); - uint64_t Freq = (Freqs[BB].getFrequency() * D) / N; - - // Should we assert it? - if (Freq > UINT32_MAX) - Freq = UINT32_MAX; - - Freqs[BB] = BlockFrequency(Freq); - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob - << ") --> " << Freqs[BB] << "\n"); - } - // All blocks in postorder. std::vector POT; // Map Block -> Position in reverse-postorder list. DenseMap RPO; - // Cycle Probability for each bloch. - DenseMap CycleProb; + // For each loop header, record the per-iteration probability of exiting the + // loop. This is the reciprocal of the expected number of loop iterations. + typedef DenseMap LoopExitProbMap; + LoopExitProbMap LoopExitProb; // (reverse-)postorder traversal iterators. typedef typename std::vector::iterator pot_iterator; @@ -123,7 +108,7 @@ class BlockFrequencyImpl { rpot_iterator rpot_at(BlockT *BB) { rpot_iterator I = rpot_begin(); - unsigned idx = RPO[BB]; + unsigned idx = RPO.lookup(BB); assert(idx); std::advance(I, idx - 1); @@ -131,22 +116,14 @@ class BlockFrequencyImpl { return I; } - - /// isReachable - Returns if BB block is reachable from the entry. - /// - bool isReachable(BlockT *BB) { - return RPO.count(BB); - } - - /// isBackedge - Return if edge Src -> Dst is a backedge. + /// isBackedge - Return if edge Src -> Dst is a reachable backedge. /// - bool isBackedge(BlockT *Src, BlockT *Dst) { - assert(isReachable(Src)); - assert(isReachable(Dst)); - - unsigned a = RPO[Src]; - unsigned b = RPO[Dst]; - + bool isBackedge(BlockT *Src, BlockT *Dst) const { + unsigned a = RPO.lookup(Src); + if (!a) + return false; + unsigned b = RPO.lookup(Dst); + assert(b && "Destination block should be reachable"); return a >= b; } @@ -196,7 +173,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB)) { + if (isBackedge(Pred, BB)) { isLoopHead = true; } else if (BlocksInLoop.count(Pred)) { incBlockFreq(BB, getEdgeFreq(Pred, BB)); @@ -211,10 +188,13 @@ class BlockFrequencyImpl { if (!isLoopHead) return; - assert(EntryFreq >= CycleProb[BB]); - uint32_t CProb = CycleProb[BB]; - uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1; - divBlockFreq(BB, BranchProbability(Numerator, EntryFreq)); + // This block is a loop header, so boost its frequency by the expected + // number of loop iterations. The loop blocks will be revisited so they all + // get this boost. + typename LoopExitProbMap::const_iterator I = LoopExitProb.find(BB); + assert(I != LoopExitProb.end() && "Loop header missing from table"); + Freqs[BB] /= I->second; + DEBUG(dbgs() << "Loop header scaled to " << Freqs[BB] << ".\n"); } /// doLoop - Propagate block frequency down through the loop. @@ -234,24 +214,50 @@ class BlockFrequencyImpl { } // Compute loop's cyclic probability using backedges probabilities. + BlockFrequency BackFreq; for (typename GT::ChildIteratorType PI = GraphTraits< Inverse >::child_begin(Head), PE = GraphTraits< Inverse >::child_end(Head); PI != PE; ++PI) { BlockT *Pred = *PI; assert(Pred); - if (isReachable(Pred) && isBackedge(Pred, Head)) { - uint64_t N = getEdgeFreq(Pred, Head).getFrequency(); - uint64_t D = getBlockFreq(Head).getFrequency(); - assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!"); - uint64_t Res = (N * EntryFreq) / D; - - assert(Res <= UINT32_MAX); - CycleProb[Head] += (uint32_t) Res; - DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res - << " --> " << CycleProb[Head] << "\n"); - } + if (isBackedge(Pred, Head)) + BackFreq += getEdgeFreq(Pred, Head); + } + + // The cyclic probability is freq(BackEdges) / freq(Head), where freq(Head) + // only counts edges entering the loop, not the loop backedges. + // The probability of leaving the loop on each iteration is: + // + // ExitProb = 1 - CyclicProb + // + // The Expected number of loop iterations is: + // + // Iterations = 1 / ExitProb + // + uint64_t D = std::max(getBlockFreq(Head).getFrequency(), UINT64_C(1)); + uint64_t N = std::max(BackFreq.getFrequency(), UINT64_C(1)); + if (N < D) + N = D - N; + else + // We'd expect N < D, but rounding and saturation means that can't be + // guaranteed. + N = 1; + + // Now ExitProb = N / D, make sure it fits in an i32/i32 fraction. + assert(N <= D); + if (D > UINT32_MAX) { + unsigned Shift = 32 - countLeadingZeros(D); + D >>= Shift; + N >>= Shift; + if (N == 0) + N = 1; } + BranchProbability LEP = BranchProbability(N, D); + LoopExitProb.insert(std::make_pair(Head, LEP)); + DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP + << " from 1 - " << BackFreq << " / " << getBlockFreq(Head) + << ".\n"); } friend class BlockFrequencyInfo; @@ -266,7 +272,7 @@ class BlockFrequencyImpl { // Clear everything. RPO.clear(); POT.clear(); - CycleProb.clear(); + LoopExitProb.clear(); Freqs.clear(); BlockT *EntryBlock = fn->begin(); @@ -292,8 +298,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB) - && (!LastTail || RPO[Pred] > RPO[LastTail])) + if (isBackedge(Pred, BB) && (!LastTail || RPO[Pred] > RPO[LastTail])) LastTail = Pred; } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index fcab90677a486..a123d0b8c1360 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========// +//===------- BlockFrequencyInfo.h - Block Frequency Analysis --*- C++ -*---===// // // The LLVM Compiler Infrastructure // @@ -41,12 +41,14 @@ public: bool runOnFunction(Function &F); void print(raw_ostream &O, const Module *M) const; + const Function *getFunction() const; + void view() const; /// getblockFreq - Return block frequency. Return 0 if we don't have the - /// information. Please note that initial frequency is equal to 1024. It means - /// that we should not rely on the value itself, but only on the comparison to - /// the other block frequencies. We do this to avoid using of floating points. - /// + /// information. Please note that initial frequency is equal to ENTRY_FREQ. It + /// means that we should not rely on the value itself, but only on the + /// comparison to the other block frequencies. We do this to avoid using of + /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; }; diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 6c23f7c3aeb3c..4ff7121728ec4 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -131,11 +131,15 @@ private: /// \brief Track the set of blocks directly succeeded by a returning block. SmallPtrSet PostDominatedByUnreachable; + /// \brief Track the set of blocks that always lead to a cold call. + SmallPtrSet PostDominatedByColdCall; + /// \brief Get sum of the block successors' weights. uint32_t getSumForBlock(const BasicBlock *BB) const; bool calcUnreachableHeuristics(BasicBlock *BB); bool calcMetadataWeights(BasicBlock *BB); + bool calcColdCallHeuristics(BasicBlock *BB); bool calcPointerHeuristics(BasicBlock *BB); bool calcLoopBranchHeuristics(BasicBlock *BB); bool calcZeroHeuristics(BasicBlock *BB); diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h new file mode 100644 index 0000000000000..e5683c8e59533 --- /dev/null +++ b/include/llvm/Analysis/CFG.h @@ -0,0 +1,83 @@ +//===-- Analysis/CFG.h - BasicBlock Analyses --------------------*- 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 performs analyses on basic blocks, and instructions +// contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFG_H +#define LLVM_ANALYSIS_CFG_H + +#include "llvm/IR/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Function; +class Instruction; +class LoopInfo; +class TerminatorInst; + +/// 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); + +/// 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); + +/// 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); + +/// \brief Determine whether instruction 'To' is reachable from 'From', +/// returning true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been executed then +/// 'To' can not be executed. Conservatively returns true. +/// +/// This function is linear with respect to the number of blocks in the CFG, +/// walking down successors from From to reach To, with a fixed threshold. +/// Using DT or LI allows us to answer more quickly. LI reduces the cost of +/// an entire loop of any number of blocsk to be the same as the cost of a +/// single block. DT reduces the cost by allowing the search to terminate when +/// we find a block that dominates the block containing 'To'. DT is most useful +/// on branchy code but not loops, and LI is most useful on code with loops but +/// does not help on branchy code outside loops. +bool isPotentiallyReachable(const Instruction *From, const Instruction *To, + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); + +/// \brief Determine whether block 'To' is reachable from 'From', returning +/// true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been reached then +/// 'To' can not be executed. Conservatively returns true. +bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index fa596c3a3c99d..39e90eb96a0f8 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -44,8 +44,9 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return OS.str(); } - static std::string getCompleteNodeLabel(const BasicBlock *Node, + static std::string getCompleteNodeLabel(const BasicBlock *Node, const Function *) { + enum { MaxColumns = 80 }; std::string Str; raw_string_ostream OS(Str); @@ -59,16 +60,32 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); // Process string output to make it nicer... - for (unsigned i = 0; i != OutStr.length(); ++i) + unsigned ColNum = 0; + unsigned LastSpace = 0; + for (unsigned i = 0; i != OutStr.length(); ++i) { if (OutStr[i] == '\n') { // Left justify OutStr[i] = '\\'; OutStr.insert(OutStr.begin()+i+1, 'l'); + ColNum = 0; + LastSpace = 0; } 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; + } else if (ColNum == MaxColumns) { // Wrap lines. + if (LastSpace) { + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. + } + // Else keep trying to find a space. } - + else + ++ColNum; + if (OutStr[i] == ' ') + LastSpace = i; + } return OutStr; } @@ -86,20 +103,20 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { 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); SwitchInst::ConstCaseIt Case = - SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); + SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); OS << Case.getCaseValue()->getValue(); return OS.str(); - } + } return ""; } }; diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 591484dd27824..d00c2ed327c55 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -69,13 +69,36 @@ class CallGraphNode; //===----------------------------------------------------------------------===// // CallGraph class definition // -class CallGraph { -protected: +class CallGraph : public ModulePass { Module *Mod; // The module this call graph represents typedef std::map FunctionMapTy; FunctionMapTy FunctionMap; // Map from a function to its node + // 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; + + /// 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); + + // Add a function to the call graph, and link the node to all of the functions + // that it calls. + void addToCallGraph(Function *F); + public: static char ID; // Class identification, replacement for typeinfo //===--------------------------------------------------------------------- @@ -107,15 +130,14 @@ public: } /// 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; } + /// into the callgraph. + CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } + CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; } /// 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; } + /// as the externalcallingnode. + CallGraphNode *getRoot() { return Root; } + const CallGraphNode *getRoot() const { return Root; } //===--------------------------------------------------------------------- // Functions to keep a call graph up to date with a function that has been @@ -129,41 +151,20 @@ public: /// 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); + CallGraph(); + virtual ~CallGraph() { releaseMemory(); } + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnModule(Module &M); + virtual void releaseMemory(); - void print(raw_ostream &o, Module *) const; + void print(raw_ostream &o, const Module *) const; void dump() const; -protected: - // destroy - Release memory for the call graph - virtual void destroy(); }; //===----------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 12e623ea9be4a..0018a567967ac 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -1,4 +1,4 @@ -//===-- ConstantFolding.h - Fold instructions into constants --------------===// +//===-- ConstantFolding.h - Fold instructions into constants ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -48,8 +48,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// 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 +/// 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, Type *DestTy, diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index a78ac5919acb3..ea8cecf97e670 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -61,11 +61,20 @@ namespace llvm { /// cases (for output, flow, and anti dependences), the dependence implies /// an ordering, where the source must precede the destination; in contrast, /// input dependences are unordered. + /// + /// When a dependence graph is built, each Dependence will be a member of + /// the set of predecessor edges for its destination instruction and a set + /// if successor edges for its source instruction. These sets are represented + /// as singly-linked lists, with the "next" fields stored in the dependence + /// itelf. class Dependence { public: Dependence(Instruction *Source, Instruction *Destination) : - Src(Source), Dst(Destination) {} + Src(Source), + Dst(Destination), + NextPredecessor(NULL), + NextSuccessor(NULL) {} virtual ~Dependence() {} /// Dependence::DVEntry - Each level in the distance/direction vector @@ -164,11 +173,36 @@ namespace llvm { /// variable associated with the loop at this level. virtual bool isScalar(unsigned Level) const; + /// getNextPredecessor - Returns the value of the NextPredecessor + /// field. + const Dependence *getNextPredecessor() const { + return NextPredecessor; + } + + /// getNextSuccessor - Returns the value of the NextSuccessor + /// field. + const Dependence *getNextSuccessor() const { + return NextSuccessor; + } + + /// setNextPredecessor - Sets the value of the NextPredecessor + /// field. + void setNextPredecessor(const Dependence *pred) { + NextPredecessor = pred; + } + + /// setNextSuccessor - Sets the value of the NextSuccessor + /// field. + void setNextSuccessor(const Dependence *succ) { + NextSuccessor = succ; + } + /// dump - For debugging purposes, dumps a dependence to OS. /// void dump(raw_ostream &OS) const; private: Instruction *Src, *Dst; + const Dependence *NextPredecessor, *NextSuccessor; friend class DependenceAnalysis; }; @@ -815,7 +849,7 @@ namespace llvm { bool propagate(const SCEV *&Src, const SCEV *&Dst, SmallBitVector &Loops, - SmallVector &Constraints, + SmallVectorImpl &Constraints, bool &Consistent); /// propagateDistance - Attempt to propagate a distance @@ -874,6 +908,10 @@ namespace llvm { /// based on the current constraint. void updateDirection(Dependence::DVEntry &Level, const Constraint &CurConstraint) const; + + bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, + SmallVectorImpl &Pair) const; + public: static char ID; // Class identification, replacement for typeinfo DependenceAnalysis() : FunctionPass(ID) { diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index 81c04bb6b0fae..3aa0beb6bb1eb 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -346,6 +346,20 @@ public: DomTreeNodeBase *getRootNode() { return RootNode; } const DomTreeNodeBase *getRootNode() const { return RootNode; } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(NodeT *R, SmallVectorImpl &Result) const { + const DomTreeNodeBase *RN = getNode(R); + SmallVector *, 8> WL; + WL.push_back(RN); + Result.clear(); + + while (!WL.empty()) { + const DomTreeNodeBase *N = WL.pop_back_val(); + Result.push_back(N->getBlock()); + WL.append(N->begin(), N->end()); + } + } + /// properlyDominates - Returns true iff A dominates B and A != B. /// Note that this is not a constant time operation! /// @@ -755,6 +769,12 @@ public: return DT->getRootNode(); } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(BasicBlock *R, + SmallVectorImpl &Result) const { + DT->getDescendants(R, Result); + } + /// compare - Return false if the other dominator tree matches this /// dominator tree. Otherwise return true. inline bool compare(DominatorTree &Other) const { diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index bc7924e10fdcb..383f69713ad27 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -14,7 +14,6 @@ #ifndef LLVM_ANALYSIS_INLINECOST_H #define LLVM_ANALYSIS_INLINECOST_H -#include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include #include @@ -77,7 +76,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - operator bool() const { + LLVM_EXPLICIT operator bool() const { return Cost < Threshold; } diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index d760a4cba1cfb..775d0df46c679 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -1,4 +1,4 @@ -//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===// +//===-- InstructionSimplify.h - Fold instrs into simpler forms --*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 783e347522d42..62f5acad56689 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -50,6 +50,7 @@ inline void RemoveFromVector(std::vector &V, T *N) { class DominatorTree; class LoopInfo; class Loop; +class MDNode; class PHINode; class raw_ostream; template class LoopInfoBase; @@ -68,6 +69,8 @@ class LoopBase { // Blocks - The list of blocks in this loop. First entry is the header node. std::vector Blocks; + SmallPtrSet DenseBlockSet; + LoopBase(const LoopBase &) LLVM_DELETED_FUNCTION; const LoopBase& operator=(const LoopBase &) LLVM_DELETED_FUNCTION; @@ -107,7 +110,7 @@ public: /// 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(); + return DenseBlockSet.count(BB); } /// contains - Return true if the specified instruction is in this loop. @@ -133,7 +136,6 @@ public: /// getBlocks - Get a list of the basic blocks which make up this loop. /// const std::vector &getBlocks() const { return Blocks; } - std::vector &getBlocksVector() { 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(); } @@ -270,6 +272,17 @@ public: /// transformations should use addBasicBlockToLoop. void addBlockEntry(BlockT *BB) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); + } + + /// reverseBlocks - interface to reverse Blocks[from, end of loop] in this loop + void reverseBlock(unsigned from) { + std::reverse(Blocks.begin() + from, Blocks.end()); + } + + /// reserveBlocks- interface to do reserve() for Blocks + void reserveBlocks(unsigned size) { + Blocks.reserve(size); } /// moveToHeader - This method is used to move BB (which must be part of this @@ -292,6 +305,7 @@ public: /// the mapping in the LoopInfo class. void removeBlockFromLoop(BlockT *BB) { RemoveFromVector(Blocks, BB); + DenseBlockSet.erase(BB); } /// verifyLoop - Verify loop structure @@ -306,6 +320,7 @@ protected: friend class LoopInfoBase; explicit LoopBase(BlockT *BB) : ParentLoop(0) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); } }; @@ -391,6 +406,22 @@ public: /// iterations. bool isAnnotatedParallel() const; + /// Return the llvm.loop loop id metadata node for this loop if it is present. + /// + /// If this loop contains the same llvm.loop metadata on each branch to the + /// header then the node is returned. If any latch instruction does not + /// contain llvm.loop or or if multiple latches contain different nodes then + /// 0 is returned. + MDNode *getLoopID() const; + /// Set the llvm.loop loop id metadata for this loop. + /// + /// The LoopID metadata node will be added to each terminator instruction in + /// the loop that branches to the loop header. + /// + /// The LoopID metadata node should have one or more operands and the first + /// operand should should be the node itself. + void setLoopID(MDNode *LoopID) const; + /// hasDedicatedExits - Return true if no exit block for the loop /// has a predecessor that is outside the loop. bool hasDedicatedExits() const; diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 5485f3c0c04c4..c98cb589108bc 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -31,17 +31,12 @@ namespace llvm { template void LoopBase:: 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)) { + if (!contains(*I)) { // Not in current loop? It must be an exit block. ExitingBlocks.push_back(*BI); break; @@ -65,17 +60,12 @@ BlockT *LoopBase::getExitingBlock() const { template void LoopBase:: 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)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitBlocks.push_back(*I); } @@ -95,17 +85,12 @@ BlockT *LoopBase::getExitBlock() const { template void LoopBase:: 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)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitEdges.push_back(Edge(*BI, *I)); } @@ -210,7 +195,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase &LIB) { // Add the basic block to this loop and all parent loops... while (L) { - L->Blocks.push_back(NewBB); + L->addBlockEntry(NewBB); L = L->getParentLoop(); } } @@ -250,11 +235,6 @@ void LoopBase::verifyLoop() const { // Keep track of the number of BBs visited. unsigned NumVisited = 0; - // 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 ( ; BI != BE; ++BI) { BlockT *BB = *BI; @@ -266,7 +246,7 @@ void LoopBase::verifyLoop() const { 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)) { + if (contains(*SI)) { HasInsideLoopSuccs = true; break; } @@ -275,7 +255,7 @@ void LoopBase::verifyLoop() const { InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); PI != PE; ++PI) { BlockT *N = *PI; - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) + if (contains(N)) HasInsideLoopPreds = true; else OutsideLoopPreds.push_back(N); @@ -309,7 +289,7 @@ void LoopBase::verifyLoop() const { // 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) && + assert(contains(*BI) && "Loop does not contain all the blocks of a subloop!"); } @@ -418,7 +398,7 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef Backedges, } } L->getSubLoopsVector().reserve(NumSubloops); - L->getBlocksVector().reserve(NumBlocks); + L->reserveBlocks(NumBlocks); } namespace { @@ -489,15 +469,14 @@ void PopulateLoopsDFS::insertIntoLoop(BlockT *Block) { // For convenience, Blocks and Subloops are inserted in postorder. Reverse // the lists, except for the loop header, which is always at the beginning. - std::reverse(Subloop->getBlocksVector().begin()+1, - Subloop->getBlocksVector().end()); + Subloop->reverseBlock(1); std::reverse(Subloop->getSubLoopsVector().begin(), Subloop->getSubLoopsVector().end()); Subloop = Subloop->getParentLoop(); } for (; Subloop; Subloop = Subloop->getParentLoop()) - Subloop->getBlocksVector().push_back(Block); + Subloop->addBlockEntry(Block); } /// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 5767c1916b39f..5926610d1aa65 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -16,8 +16,8 @@ #define LLVM_ANALYSIS_LOOPPASS_H #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include namespace llvm { diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 488338302adac..91224ad94ac29 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This family of functions identifies calls to builtin functions that allocate -// or free memory. +// or free memory. // //===----------------------------------------------------------------------===// @@ -64,6 +64,10 @@ bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates memory and never returns null (such as operator new). +bool isOperatorNewLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); //===----------------------------------------------------------------------===// // malloc Call Utility Functions. @@ -78,10 +82,10 @@ static inline CallInst *extractMallocCall(Value *I, return const_cast(extractMallocCall((const Value*)I, TLI)); } -/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// 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 DataLayout *TD, +const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL, const TargetLibraryInfo *TLI); /// getMallocType - Returns the PointerType resulting from the malloc call. @@ -98,12 +102,12 @@ PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI); /// >1: Unique PointerType cannot be determined, return NULL. Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); -/// getMallocArraySize - Returns the array size of a malloc call. If the +/// 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 DataLayout *TD, +Value *getMallocArraySize(CallInst *CI, const DataLayout *DL, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); @@ -127,12 +131,12 @@ static inline CallInst *extractCallocCall(Value *I, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI); - + static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { return const_cast(isFreeCall((const Value*)I, TLI)); } - + //===----------------------------------------------------------------------===// // Utility functions to compute size of objects. // @@ -143,19 +147,19 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// underlying object pointed to by Ptr. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. -bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false); typedef std::pair SizeOffsetType; -/// \brief Evaluate the size and offset of an object ponted by a Value* +/// \brief Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor : public InstVisitor { - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; @@ -169,7 +173,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -206,7 +210,7 @@ public: typedef std::pair SizeOffsetEvalType; -/// \brief Evaluate the size and offset of an object ponted by a Value*. +/// \brief Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor { @@ -216,7 +220,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap CacheMapTy; typedef SmallPtrSet PtrSetTy; - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -224,6 +228,7 @@ class ObjectSizeOffsetEvaluator Value *Zero; CacheMapTy CacheMap; PtrSetTy SeenVals; + bool RoundToAlign; SizeOffsetEvalType unknown() { return std::make_pair((Value*)0, (Value*)0); @@ -231,8 +236,8 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI, - LLVMContext &Context); + ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, + LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); bool knownSize(SizeOffsetEvalType SizeOffset) { diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index ae117135db93b..a5d098eb0d9ca 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -93,64 +93,6 @@ namespace llvm { // ImmutablePass *createObjCARCAliasAnalysisPass(); - //===--------------------------------------------------------------------===// - // - // createProfileLoaderPass - This pass loads information from a profile dump - // file. - // - ModulePass *createProfileLoaderPass(); - extern char &ProfileLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createProfileMetadataLoaderPass - This pass loads information from a - // profile dump file and sets branch weight metadata. - // - ModulePass *createProfileMetadataLoaderPass(); - extern char &ProfileMetadataLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // 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 @@ -192,6 +134,13 @@ namespace llvm { // FunctionPass *createCostModelAnalysisPass(); + //===--------------------------------------------------------------------===// + // + // createDelinearizationPass - This pass implements attempts to restore + // multidimensional array indices from linearized expressions. + // + FunctionPass *createDelinearizationPass(); + //===--------------------------------------------------------------------===// // // Minor pass prototypes, allowing us to expose them through bugpoint and diff --git a/include/llvm/Analysis/PathNumbering.h b/include/llvm/Analysis/PathNumbering.h deleted file mode 100644 index 400a37d8293fb..0000000000000 --- a/include/llvm/Analysis/PathNumbering.h +++ /dev/null @@ -1,304 +0,0 @@ -//===- 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_ANALYSIS_PATHNUMBERING_H -#define LLVM_ANALYSIS_PATHNUMBERING_H - -#include "llvm/Analysis/ProfileInfoTypes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/CFG.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/include/llvm/Analysis/PathProfileInfo.h b/include/llvm/Analysis/PathProfileInfo.h deleted file mode 100644 index 4fce16ef0d560..0000000000000 --- a/include/llvm/Analysis/PathProfileInfo.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- 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_ANALYSIS_PATHPROFILEINFO_H -#define LLVM_ANALYSIS_PATHPROFILEINFO_H - -#include "llvm/Analysis/PathNumbering.h" -#include "llvm/IR/BasicBlock.h" - -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/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index d082297454a1d..88ebab4edecfb 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -74,6 +74,11 @@ struct PostDominatorTree : public FunctionPass { return DT->findNearestCommonDominator(A, B); } + inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A, + const BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + virtual void releaseMemory() { DT->releaseMemory(); } diff --git a/include/llvm/Analysis/ProfileDataLoader.h b/include/llvm/Analysis/ProfileDataLoader.h deleted file mode 100644 index 90097f79951d3..0000000000000 --- a/include/llvm/Analysis/ProfileDataLoader.h +++ /dev/null @@ -1,140 +0,0 @@ -//===- ProfileDataLoader.h - Load & convert profile info ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The ProfileDataLoader class is used to load profiling data from a dump file. -// The ProfileDataT class is used to store the mapping of this -// data to control flow edges. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEDATALOADER_H -#define LLVM_ANALYSIS_PROFILEDATALOADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include - -namespace llvm { - -class ModulePass; -class Function; -class BasicBlock; - -// Helper for dumping edges to dbgs(). -raw_ostream& operator<<(raw_ostream &O, std::pair E); - -/// \brief The ProfileDataT class is used to store the mapping of -/// profiling data to control flow edges. -/// -/// An edge is defined by its source and sink basic blocks. -template -class ProfileDataT { -public: - // The profiling information defines an Edge by its source and sink basic - // blocks. - typedef std::pair Edge; - -private: - typedef DenseMap EdgeWeights; - - /// \brief 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. - DenseMap EdgeInformation; - -public: - /// getFunction() - Returns the Function for an Edge. - static const FType *getFunction(Edge e) { - // e.first may be NULL - assert(((!e.first) || (e.first->getParent() == e.second->getParent())) - && "A ProfileData::Edge can not be between two functions"); - assert(e.second && "A ProfileData::Edge must have a real sink"); - return e.second->getParent(); - } - - /// getEdge() - Creates an Edge between two BasicBlocks. - static Edge getEdge(const BType *Src, const BType *Dest) { - return Edge(Src, Dest); - } - - /// getEdgeWeight - Return the number of times that a given edge was - /// executed. - unsigned getEdgeWeight(Edge e) const { - const FType *f = getFunction(e); - assert((EdgeInformation.find(f) != EdgeInformation.end()) - && "No profiling information for function"); - EdgeWeights weights = EdgeInformation.find(f)->second; - - assert((weights.find(e) != weights.end()) - && "No profiling information for edge"); - return weights.find(e)->second; - } - - /// addEdgeWeight - Add 'weight' to the already stored execution count for - /// this edge. - void addEdgeWeight(Edge e, unsigned weight) { - EdgeInformation[getFunction(e)][e] += weight; - } -}; - -typedef ProfileDataT ProfileData; -//typedef ProfileDataT MachineProfileData; - -/// The ProfileDataLoader class is used to load raw profiling data from the -/// dump file. -class ProfileDataLoader { -private: - /// The name of the file where the raw profiling data is stored. - const std::string &Filename; - - /// A vector of the command line arguments used when the target program was - /// run to generate profiling data. One entry per program run. - SmallVector CommandLines; - - /// The raw values for how many times each edge was traversed, values from - /// multiple program runs are accumulated. - SmallVector EdgeCounts; - -public: - /// ProfileDataLoader ctor - Read the specified profiling data file, exiting - /// the program if the file is invalid or broken. - ProfileDataLoader(const char *ToolName, const std::string &Filename); - - /// A special value used to represent the weight of an edge which has not - /// been counted yet. - static const unsigned Uncounted; - - /// getNumExecutions - Return the number of times the target program was run - /// to generate this profiling data. - unsigned getNumExecutions() const { return CommandLines.size(); } - - /// getExecution - Return the command line parameters used to generate the - /// i'th set of profiling data. - const std::string &getExecution(unsigned i) const { return CommandLines[i]; } - - const std::string &getFileName() const { return Filename; } - - /// getRawEdgeCounts - Return the raw profiling data, this is just a list of - /// numbers with no mappings to edges. - ArrayRef getRawEdgeCounts() const { return EdgeCounts; } -}; - -/// createProfileMetadataLoaderPass - This function returns a Pass that loads -/// the profiling information for the module from the specified filename. -ModulePass *createProfileMetadataLoaderPass(const std::string &Filename); - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/ProfileDataTypes.h b/include/llvm/Analysis/ProfileDataTypes.h deleted file mode 100644 index 1be15e025da9d..0000000000000 --- a/include/llvm/Analysis/ProfileDataTypes.h +++ /dev/null @@ -1,39 +0,0 @@ -/*===-- ProfileDataTypes.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 metadata loader. It must be a -|* C header because, at present, the profiling runtimes are written in C. -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_ANALYSIS_PROFILEDATATYPES_H -#define LLVM_ANALYSIS_PROFILEDATATYPES_H - -/* Included by libprofile. */ -#if defined(__cplusplus) -extern "C" { -#endif - -/* TODO: Strip out unused entries once ProfileInfo etc has been removed. */ -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 */ -}; - -#if defined(__cplusplus) -} -#endif - -#endif /* LLVM_ANALYSIS_PROFILEDATATYPES_H */ diff --git a/include/llvm/Analysis/ProfileInfo.h b/include/llvm/Analysis/ProfileInfo.h deleted file mode 100644 index 5d17fa1220e10..0000000000000 --- a/include/llvm/Analysis/ProfileInfo.h +++ /dev/null @@ -1,247 +0,0 @@ -//===- 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/ErrorHandling.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(); - if (e.second) - return e.second->getParent(); - llvm_unreachable("Invalid ProfileInfo::Edge"); - } - - // 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/include/llvm/Analysis/ProfileInfoLoader.h b/include/llvm/Analysis/ProfileInfoLoader.h deleted file mode 100644 index e0f49f3179bc6..0000000000000 --- a/include/llvm/Analysis/ProfileInfoLoader.h +++ /dev/null @@ -1,81 +0,0 @@ -//===- 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; - std::vector CommandLines; - std::vector FunctionCounts; - std::vector BlockCounts; - std::vector EdgeCounts; - std::vector OptimalEdgeCounts; - std::vector BBTrace; -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); - - 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/include/llvm/Analysis/ProfileInfoTypes.h b/include/llvm/Analysis/ProfileInfoTypes.h deleted file mode 100644 index 45aab5b70d2b1..0000000000000 --- a/include/llvm/Analysis/ProfileInfoTypes.h +++ /dev/null @@ -1,52 +0,0 @@ -/*===-- 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 -}; - -#include "llvm/Analysis/ProfileDataTypes.h" - -/* - * 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/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 0690ac5e34a77..3907ad9c7dd5e 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -18,8 +18,8 @@ #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include namespace llvm { @@ -51,7 +51,7 @@ public: /// @brief Get a pass to print the LLVM IR in the region. /// - /// @param O The ouput stream to print the Region. + /// @param O The output stream to print the Region. /// @param Banner The banner to separate different printed passes. /// /// @return The pass to print the LLVM IR in the region. diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 349447fbbb624..d7f6178171798 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -189,15 +189,16 @@ namespace llvm { /// Convenient NoWrapFlags manipulation that hides enum casts and is /// visible in the ScalarEvolution name space. - static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, int Mask) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + maskFlags(SCEV::NoWrapFlags Flags, int Mask) { return (SCEV::NoWrapFlags)(Flags & Mask); } - static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OnFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + setFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OnFlags) { return (SCEV::NoWrapFlags)(Flags | OnFlags); } - static SCEV::NoWrapFlags clearFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OffFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + clearFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OffFlags) { return (SCEV::NoWrapFlags)(Flags & ~OffFlags); } @@ -361,18 +362,18 @@ namespace llvm { /// that we attempt to compute getSCEVAtScope information for, which can /// be expensive in extreme cases. DenseMap > ValuesAtScopes; + SmallVector, 2> > ValuesAtScopes; /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap > LoopDispositions; + SmallVector, 2> > LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. DenseMap > BlockDispositions; + SmallVector, 2> > BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); @@ -426,14 +427,6 @@ namespace llvm { /// 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. @@ -498,6 +491,8 @@ namespace llvm { /// less-than is signed. ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned, bool IsSubExpr); + ExitLimit HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned, bool IsSubExpr); /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB /// (which may not be an immediate predecessor) which has exactly one @@ -545,6 +540,10 @@ namespace llvm { /// forgetMemoizedResults - Drop memoized information computed for S. void forgetMemoizedResults(const SCEV *S); + /// Return false iff given SCEV contains a SCEVUnknown with NULL value- + /// pointer. + bool checkValidity(const SCEV *S) const; + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -632,21 +631,15 @@ namespace llvm { const SCEV *getUnknown(Value *V); const SCEV *getCouldNotCompute(); - /// getSizeOfExpr - Return an expression for sizeof on the given type. - /// - const SCEV *getSizeOfExpr(Type *AllocTy); - - /// getAlignOfExpr - Return an expression for alignof on the given type. + /// getSizeOfExpr - Return an expression for sizeof AllocTy that is type + /// IntTy /// - const SCEV *getAlignOfExpr(Type *AllocTy); + const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); - /// getOffsetOfExpr - Return an expression for offsetof on the given field. + /// getOffsetOfExpr - Return an expression for offsetof on the given field + /// with type IntTy /// - const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo); - - /// getOffsetOfExpr - Return an expression for offsetof on the given field. - /// - const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo); + const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); /// getNegativeSCEV - Return the SCEV object corresponding to -V. /// @@ -881,6 +874,24 @@ namespace llvm { virtual void print(raw_ostream &OS, const Module* = 0) const; virtual void verifyAnalysis() const; + private: + /// Compute the backedge taken count knowing the interval difference, the + /// stride and presence of the equality in the comparison. + const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, + bool Equality); + + /// Verify if an linear IV with positive stride can overflow when in a + /// less-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + + /// Verify if an linear IV with negative stride can overflow when in a + /// greater-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + private: FoldingSet UniqueSCEVs; BumpPtrAllocator SCEVAllocator; diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 00779fc329b11..4433be000d774 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -26,7 +26,7 @@ namespace llvm { /// Return true if the given expression is safe to expand in the sense that /// all materialized values are safe to speculate. - bool isSafeToExpand(const SCEV *S); + bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); /// SCEVExpander - This class uses information about analyze scalars to /// rewrite expressions in canonical form. @@ -252,8 +252,6 @@ namespace llvm { void rememberInstruction(Value *I); - void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I); - bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index eac91131ad535..9cd902a120cff 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -351,8 +351,14 @@ namespace llvm { static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddRecExpr; } - }; + /// Splits the SCEV into two vectors of SCEVs representing the subscripts + /// and sizes of an array access. Returns the remainder of the + /// delinearization that is the offset start of the array. + const SCEV *delinearize(ScalarEvolution &SE, + SmallVectorImpl &Subscripts, + SmallVectorImpl &Sizes) const; + }; //===--------------------------------------------------------------------===// /// SCEVSMaxExpr - This class represents a signed maximum selection. @@ -549,53 +555,60 @@ namespace llvm { T.visitAll(Root); } - /// The SCEVRewriter takes a scalar evolution expression and copies all its - /// components. The result after a rewrite is an identical SCEV. - struct SCEVRewriter - : public SCEVVisitor { + typedef DenseMap ValueToValueMap; + + /// The SCEVParameterRewriter takes a scalar evolution expression and updates + /// the SCEVUnknown components following the Map (Value -> Value). + struct SCEVParameterRewriter + : public SCEVVisitor { public: - SCEVRewriter(ScalarEvolution &S) : SE(S) {} + static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, + ValueToValueMap &Map) { + SCEVParameterRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } - virtual ~SCEVRewriter() {} + SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) + : SE(S), Map(M) {} - virtual const SCEV *visitConstant(const SCEVConstant *Constant) { + const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; } - virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getTruncateExpr(Operand, Expr->getType()); } - virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getZeroExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getSignExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getAddExpr(Operands); } - virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getMulExpr(Operands); } - virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -603,54 +616,33 @@ namespace llvm { Expr->getNoWrapFlags()); } - virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getSMaxExpr(Operands); } - virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getUMaxExpr(Operands); } - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { - return Expr; - } - - virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { - return Expr; - } - - protected: - ScalarEvolution &SE; - }; - - typedef DenseMap ValueToValueMap; - - /// The SCEVParameterRewriter takes a scalar evolution expression and updates - /// the SCEVUnknown components following the Map (Value -> Value). - struct SCEVParameterRewriter: public SCEVRewriter { - public: - static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, - ValueToValueMap &Map) { - SCEVParameterRewriter Rewriter(SE, Map); - return Rewriter.visit(Scev); - } - SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) - : SCEVRewriter(S), Map(M) {} - - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { + const SCEV *visitUnknown(const SCEVUnknown *Expr) { Value *V = Expr->getValue(); if (Map.count(V)) return SE.getUnknown(Map[V]); return Expr; } + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; ValueToValueMap ⤅ }; @@ -658,17 +650,56 @@ namespace llvm { /// The SCEVApplyRewriter takes a scalar evolution expression and applies /// the Map (Loop -> SCEV) to all AddRecExprs. - struct SCEVApplyRewriter: public SCEVRewriter { + struct SCEVApplyRewriter + : public SCEVVisitor { public: static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map, ScalarEvolution &SE) { SCEVApplyRewriter Rewriter(SE, Map); return Rewriter.visit(Scev); } + SCEVApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M) - : SCEVRewriter(S), Map(M) {} + : SE(S), Map(M) {} + + const SCEV *visitConstant(const SCEVConstant *Constant) { + return Constant; + } + + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getTruncateExpr(Operand, Expr->getType()); + } + + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getZeroExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getSignExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getAddExpr(Operands); + } + + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getMulExpr(Operands); + } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); + } + + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -683,7 +714,30 @@ namespace llvm { return Rec->evaluateAtIteration(Map[L], SE); } + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getSMaxExpr(Operands); + } + + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getUMaxExpr(Operands); + } + + const SCEV *visitUnknown(const SCEVUnknown *Expr) { + return Expr; + } + + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; LoopToScevMapT ⤅ }; diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index a9d6725d86b09..4f47562389299 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -29,6 +29,7 @@ namespace llvm { class GlobalValue; +class Loop; class Type; class User; class Value; @@ -171,6 +172,12 @@ public: /// comments for a detailed explanation of the cost values. virtual unsigned getUserCost(const User *U) const; + /// \brief hasBranchDivergence - Return true if branch divergence exists. + /// Branch divergence has a significantly negative impact on GPU performance + /// when threads in the same wavefront take different paths due to conditional + /// branches. + virtual bool hasBranchDivergence() const; + /// \brief Test whether calls to a function lower to actual program function /// calls. /// @@ -185,6 +192,36 @@ public: /// incurs significant execution cost. virtual bool isLoweredToCall(const Function *F) const; + /// Parameters that control the generic loop unrolling transformation. + struct UnrollingPreferences { + /// The cost threshold for the unrolled loop, compared to + /// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body. + /// The unrolling factor is set such that the unrolled loop body does not + /// exceed this cost. Set this to UINT_MAX to disable the loop body cost + /// restriction. + unsigned Threshold; + /// The cost threshold for the unrolled loop when optimizing for size (set + /// to UINT_MAX to disable). + unsigned OptSizeThreshold; + /// A forced unrolling factor (the number of concatenated bodies of the + /// original loop in the unrolled loop body). When set to 0, the unrolling + /// transformation will select an unrolling factor based on the current cost + /// threshold and other factors. + unsigned Count; + /// Allow partial unrolling (unrolling of loops to expand the size of the + /// loop body, not only to eliminate small constant-trip-count loops). + bool Partial; + /// Allow runtime unrolling (unrolling of loops to expand the size of the + /// loop body even when the number of loop iterations is not known at compile + /// time). + bool Runtime; + }; + + /// \brief Get target-customized preferences for the generic loop unrolling + /// transformation. The caller will initialize UP with the current + /// target-independent defaults. + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; + /// @} /// \name Scalar Target Information @@ -225,6 +262,16 @@ public: int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const; + /// \brief Return the cost of the scaling factor used in the addressing + /// mode represented by AM for this target, for a load/store + /// of the specified type. + /// If the AM is supported, the return value must be >= 0. + /// If the AM is not supported, it returns a negative value. + /// TODO: Handle pre/postinc as well. + virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) 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. @@ -246,6 +293,10 @@ public: /// getPopcntSupport - Return hardware support for population count. virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + /// haveFastSqrt -- Return true if the hardware has a fast square-root + /// instruction. + virtual bool haveFastSqrt(Type *Ty) const; + /// getIntImmCost - Return the expected cost of materializing the given /// integer immediate of the specified type. virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; @@ -263,7 +314,7 @@ public: SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; - /// \brief Additonal information about an operand's possible values. + /// \brief Additional information about an operand's possible values. enum OperandValueKind { OK_AnyValue, // Operand can have any value. OK_UniformValue, // Operand is uniform (splat of a value). @@ -317,6 +368,22 @@ public: unsigned Alignment, unsigned AddressSpace) const; + /// \brief Calculate the cost of performing a vector reduction. + /// + /// This is the cost of reducing the vector value of type \p Ty to a scalar + /// value using the operation denoted by \p Opcode. The form of the reduction + /// can either be a pairwise reduction or a reduction that splits the vector + /// at every reduction level. + /// + /// Pairwise: + /// (v0, v1, v2, v3) + /// ((v0+v1), (v2, v3), undef, undef) + /// Split: + /// (v0, v1, v2, v3) + /// ((v0+v2), (v1+v3), undef, undef) + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) const; + /// \returns The cost of Intrinsic instructions. virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef Tys) const; @@ -329,7 +396,11 @@ public: /// merged into the instruction indexing mode. Some targets might want to /// distinguish between address computation for memory operations on vector /// types and scalar types. Such targets should override this function. - virtual unsigned getAddressComputationCost(Type *Ty) const; + /// The 'IsComplex' parameter is a hint that the address computation is likely + /// to involve multiple instructions and as such unlikely to be merged into + /// the address indexing mode. + virtual unsigned getAddressComputationCost(Type *Ty, + bool IsComplex = false) const; /// @} diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 3775ec9f07aa8..0392f98f075e1 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,6 +25,7 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; + class TargetLibraryInfo; /// ComputeMaskedBits - Determine which of the bits specified in Mask are /// known to be either zero or one and return them in the KnownZero/KnownOne @@ -186,7 +187,7 @@ namespace llvm { /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. - bool isKnownNonNull(const Value *V); + bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = 0); } // end namespace llvm diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h index e13c4c12b0f4a..c774782f19ec5 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/AutoUpgrade.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// These functions are implemented by lib/VMCore/AutoUpgrade.cpp. +// These functions are implemented by lib/IR/AutoUpgrade.cpp. // //===----------------------------------------------------------------------===// @@ -15,30 +15,52 @@ #define LLVM_AUTOUPGRADE_H namespace llvm { + class CallInst; + class Constant; + class Function; + class Instruction; class Module; class GlobalVariable; - class Function; - class CallInst; + class Type; + class Value; - /// This is a more granular function that simply checks an intrinsic function + /// 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 + /// 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 + + /// 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); + + /// If the TBAA tag for the given instruction uses the scalar TBAA format, + /// we upgrade it to the struct-path aware TBAA format. + void UpgradeInstWithTBAATag(Instruction *I); + + /// This is an auto-upgrade for bitcast between pointers with different + /// address spaces: the instruction is replaced by a pair ptrtoint+inttoptr. + Instruction *UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy, + Instruction *&Temp); + + /// This is an auto-upgrade for bitcast constant expression between pointers + /// with different address spaces: the instruction is replaced by a pair + /// ptrtoint+inttoptr. + Value *UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy); + + /// Check the debug info version number, if it is out-dated, drop the debug + /// info. Return true if module is modified. + bool UpgradeDebugInfo(Module &M); } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h deleted file mode 100644 index 7b30c7e458faf..0000000000000 --- a/include/llvm/Bitcode/Archive.h +++ /dev/null @@ -1,538 +0,0 @@ -//===-- 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 { - SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table - BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table - LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table - BitcodeFlag = 8, ///< Member is bitcode - HasPathFlag = 16, ///< Member has a full or partial path - HasLongFilenameFlag = 32, ///< Member uses the long filename syntax - StringTableFlag = 64 ///< 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; } - - /// @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 - SmallVectorImpl& 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 - 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 occurred, 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 if writing member succeeded, - /// returns true if 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? - 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() LLVM_DELETED_FUNCTION; - Archive(const Archive&) LLVM_DELETED_FUNCTION; - Archive& operator=(const Archive&) LLVM_DELETED_FUNCTION; - /// @} -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index f3139739cd18f..dc5e095155fb9 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -244,7 +244,7 @@ public: uint32_t getWord(size_t pos) { uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL); + BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf); return *reinterpret_cast(buf); } @@ -366,8 +366,7 @@ public: // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), - Array, NULL); + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); // Handle big-endian byte-swapping if necessary. support::detail::packed_endian_specific_integral diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index a837211875f59..f40a0d1d259fb 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -381,7 +381,8 @@ private: BlobData = 0; } else { for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { - assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); + assert(isUInt<8>(Vals[RecordIdx]) && + "Value too large to emit as blob"); WriteByte((unsigned char)Vals[RecordIdx]); } } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index f9690d5b779c0..b3d24661d70be 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -194,7 +194,8 @@ namespace bitc { CAST_FPEXT = 8, CAST_PTRTOINT = 9, CAST_INTTOPTR = 10, - CAST_BITCAST = 11 + CAST_BITCAST = 11, + CAST_ADDRSPACECAST = 12 }; /// BinaryOpcodes - These are values used in the bitcode files to encode which @@ -330,6 +331,48 @@ namespace bitc { enum UseListCodes { USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD. }; + + enum AttributeKindCodes { + // = 0 is unused + ATTR_KIND_ALIGNMENT = 1, + ATTR_KIND_ALWAYS_INLINE = 2, + ATTR_KIND_BY_VAL = 3, + ATTR_KIND_INLINE_HINT = 4, + ATTR_KIND_IN_REG = 5, + ATTR_KIND_MIN_SIZE = 6, + ATTR_KIND_NAKED = 7, + ATTR_KIND_NEST = 8, + ATTR_KIND_NO_ALIAS = 9, + ATTR_KIND_NO_BUILTIN = 10, + ATTR_KIND_NO_CAPTURE = 11, + ATTR_KIND_NO_DUPLICATE = 12, + ATTR_KIND_NO_IMPLICIT_FLOAT = 13, + ATTR_KIND_NO_INLINE = 14, + ATTR_KIND_NON_LAZY_BIND = 15, + ATTR_KIND_NO_RED_ZONE = 16, + ATTR_KIND_NO_RETURN = 17, + ATTR_KIND_NO_UNWIND = 18, + ATTR_KIND_OPTIMIZE_FOR_SIZE = 19, + ATTR_KIND_READ_NONE = 20, + ATTR_KIND_READ_ONLY = 21, + ATTR_KIND_RETURNED = 22, + ATTR_KIND_RETURNS_TWICE = 23, + ATTR_KIND_S_EXT = 24, + ATTR_KIND_STACK_ALIGNMENT = 25, + ATTR_KIND_STACK_PROTECT = 26, + ATTR_KIND_STACK_PROTECT_REQ = 27, + ATTR_KIND_STACK_PROTECT_STRONG = 28, + ATTR_KIND_STRUCT_RET = 29, + ATTR_KIND_SANITIZE_ADDRESS = 30, + ATTR_KIND_SANITIZE_THREAD = 31, + ATTR_KIND_SANITIZE_MEMORY = 32, + ATTR_KIND_UW_TABLE = 33, + ATTR_KIND_Z_EXT = 34, + ATTR_KIND_BUILTIN = 35, + ATTR_KIND_COLD = 36, + ATTR_KIND_OPTIMIZE_NONE = 37 + }; + } // End bitc namespace } // End llvm namespace diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index ce9ca0a0583a3..b2cc7047b30b7 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -26,6 +26,7 @@ namespace llvm { class GlobalVariable; class TargetLowering; +class TargetLoweringBase; class SDNode; class SDValue; class SelectionDAG; @@ -88,6 +89,14 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// This function only tests target-independent requirements. bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); +/// Test if given that the input instruction is in the tail call position if the +/// return type or any attributes of the function will inhibit tail call +/// optimization. +bool returnTypeIsEligibleForTailCall(const Function *F, + const Instruction *I, + const ReturnInst *Ret, + const TargetLoweringBase &TLI); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index c2fd6ce3679cc..4bda0f1603acb 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -38,9 +38,10 @@ namespace llvm { class MachineConstantPoolValue; class MachineJumpTableInfo; class MachineModuleInfo; - class MachineMove; class MCAsmInfo; + class MCCFIInstruction; class MCContext; + class MCInstrInfo; class MCSection; class MCStreamer; class MCSymbol; @@ -64,6 +65,7 @@ namespace llvm { /// const MCAsmInfo *MAI; + const MCInstrInfo *MII; /// 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. @@ -121,6 +123,8 @@ namespace llvm { public: virtual ~AsmPrinter(); + const DwarfDebug *getDwarfDebug() const { return DD; } + /// isVerbose - Return true if assembly output should contain comments. /// bool isVerbose() const { return VerboseAsm; } @@ -141,6 +145,7 @@ namespace llvm { /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; + MCSymbol *getSymbol(const GlobalValue *GV) const; //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. @@ -233,8 +238,8 @@ namespace llvm { /// 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); + /// \brief Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV); //===------------------------------------------------------------------===// @@ -282,6 +287,10 @@ namespace llvm { virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + /// emitImplicitDef - Targets can override this to customize the output of + /// IMPLICIT_DEF instructions in verbose mode. + virtual void emitImplicitDef(const MachineInstr *MI) const; + //===------------------------------------------------------------------===// // Symbol Lowering Routines. //===------------------------------------------------------------------===// @@ -357,13 +366,15 @@ namespace llvm { /// 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; + unsigned Size, + bool IsSectionRelative = false) const; /// EmitLabelReference - Emit something like ".long Label" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. - void EmitLabelReference(const MCSymbol *Label, unsigned Size) const { - EmitLabelPlusOffset(Label, 0, Size); + void EmitLabelReference(const MCSymbol *Label, unsigned Size, + bool IsSectionRelative = false) const { + EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); } //===------------------------------------------------------------------===// @@ -371,10 +382,10 @@ namespace llvm { //===------------------------------------------------------------------===// /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int Value, const char *Desc = 0) const; + void EmitSLEB128(int64_t Value, const char *Desc = 0) const; /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0, + void EmitULEB128(uint64_t Value, const char *Desc = 0, unsigned PadTo = 0) const; /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. @@ -402,24 +413,20 @@ namespace llvm { 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; } /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const; + virtual void EmitDwarfRegOp(const MachineLocation &MLoc, + bool Indirect) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines //===------------------------------------------------------------------===// - /// EmitCFIFrameMove - Emit frame instruction to describe the layout of the - /// frame. - void EmitCFIFrameMove(const MachineMove &Move) const; + /// \brief Emit frame instruction to describe the layout of the frame. + void emitCFIInstruction(const MCCFIInstruction &Inst) const; //===------------------------------------------------------------------===// // Inline Asm Support @@ -451,8 +458,7 @@ namespace llvm { /// return true if the operand is erroneous. virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); private: /// Private state for PrintSpecial() @@ -464,7 +470,8 @@ namespace llvm { /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0, - InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; + InlineAsm::AsmDialect AsmDialect = + InlineAsm::AD_ATT) const; /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. @@ -479,12 +486,13 @@ namespace llvm { void EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition = true) const; - void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const; + const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const ConstantArray *InitList); + /// Emit llvm.ident metadata in an '.ident' directive. + void EmitModuleIdents(Module &M); void EmitXXStructorList(const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 9cd2decfacff0..0d79b1d41bdbc 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -18,9 +18,12 @@ namespace llvm { class LiveInterval; class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineLoopInfo; - /// normalizeSpillWeight - The spill weight of a live interval is computed as: + /// \brief Normalize the spill weight of a live interval + /// + /// The spill weight of a live interval is computed as: /// /// (sum(use freq) + sum(def freq)) / (K + size) /// @@ -37,42 +40,38 @@ namespace llvm { return UseDefFreq / (Size + 25*SlotIndex::InstrDist); } - /// VirtRegAuxInfo - Calculate auxiliary information for a virtual - /// register such as its spill weight and allocation hint. + /// \brief Calculate auxiliary information for a virtual register such as its + /// spill weight and allocation hint. class VirtRegAuxInfo { + public: + typedef float (*NormalizingFn)(float, unsigned); + + private: MachineFunction &MF; LiveIntervals &LIS; const MachineLoopInfo &Loops; + const MachineBlockFrequencyInfo &MBFI; DenseMap Hint; + NormalizingFn normalize; + public: VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, - const MachineLoopInfo &loops) : - MF(mf), LIS(lis), Loops(loops) {} + const MachineLoopInfo &loops, + const MachineBlockFrequencyInfo &mbfi, + NormalizingFn norm = normalizeSpillWeight) + : MF(mf), LIS(lis), Loops(loops), MBFI(mbfi), normalize(norm) {} - /// CalculateWeightAndHint - (re)compute li's spill weight and allocation - /// hint. - void CalculateWeightAndHint(LiveInterval &li); + /// \brief (re)compute li's spill weight and allocation hint. + void calculateSpillWeightAndHint(LiveInterval &li); }; - /// CalculateSpillWeights - Compute spill weights for all virtual register + /// \brief Compute spill weights and allocation hints 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; - }; - + void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, + const MachineLoopInfo &MLI, + const MachineBlockFrequencyInfo &MBFI, + VirtRegAuxInfo::NormalizingFn norm = + normalizeSpillWeight); } #endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index fa9d60f0d4174..a18f433bda405 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -158,7 +158,7 @@ private: MachineFunction &MF; const TargetMachine &TM; const TargetRegisterInfo &TRI; - SmallVector &Locs; + SmallVectorImpl &Locs; LLVMContext &Context; unsigned StackOffset; @@ -219,7 +219,7 @@ protected: public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVector &locs, + const TargetMachine &TM, SmallVectorImpl &locs, LLVMContext &C); void addLoc(const CCValAssign &V) { diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 9a27661b51904..bc8dce33356e4 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -109,11 +109,6 @@ DisableFPElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization"), cl::init(false)); -cl::opt -DisableFPElimNonLeaf("disable-non-leaf-fp-elim", - cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), - cl::init(false)); - cl::opt EnableUnsafeFPMath("enable-unsafe-fp-math", cl::desc("Enable optimizations that may decrease FP precision"), @@ -155,7 +150,7 @@ FloatABIForCalls("float-abi", cl::opt FuseFPOps("fp-contract", - cl::desc("Enable aggresive formation of fused FP ops"), + cl::desc("Enable aggressive formation of fused FP ops"), cl::init(FPOpFusion::Standard), cl::values( clEnumValN(FPOpFusion::Fast, "fast", @@ -186,11 +181,6 @@ OverrideStackAlignment("stack-alignment", cl::desc("Override default stack alignment"), cl::init(0)); -cl::opt -EnableRealignStack("realign-stack", - cl::desc("Realign stack if needed"), - cl::init(true)); - cl::opt TrapFuncName("trap-func", cl::Hidden, cl::desc("Emit a call to trap function rather than a trap instruction"), @@ -220,8 +210,4 @@ cl::opt StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); -cl::opt -SSPBufferSize("stack-protector-buffer-size", cl::init(8), - cl::desc("Lower bound for a buffer to be considered for " - "stack protection")); #endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 471e9bfc40bb3..1e0ef6b545eac 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -1,4 +1,4 @@ -//===-- FastISel.h - Definition of the FastISel class ---------------------===// +//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===// // // The LLVM Compiler Infrastructure // @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FastISel class. -// +/// +/// \file +/// This file defines the FastISel class. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_FASTISEL_H @@ -26,7 +27,6 @@ class ConstantFP; class FunctionLoweringInfo; class Instruction; class LoadInst; -class MachineBasicBlock; class MachineConstantPool; class MachineFunction; class MachineInstr; @@ -42,9 +42,8 @@ class TargetRegisterInfo; class User; class Value; -/// 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. +/// 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; @@ -60,99 +59,92 @@ protected: const TargetRegisterInfo &TRI; const TargetLibraryInfo *LibInfo; - /// The position of the last instruction for materializing constants - /// for use in the current block. It resets to EmitStartPt when it - /// makes sense (for example, it's usually profitable to avoid function - /// calls between the definition and the use) + /// The position of the last instruction for materializing constants for use + /// in the current block. It resets to EmitStartPt when it makes sense (for + /// example, it's usually profitable to avoid function calls between the + /// definition and the use) MachineInstr *LastLocalValue; - /// The top most instruction in the current block that is allowed for - /// emitting local variables. LastLocalValue resets to EmitStartPt when - /// it makes sense (for example, on function calls) + /// The top most instruction in the current block that is allowed for emitting + /// local variables. LastLocalValue resets to EmitStartPt when it makes sense + /// (for example, on function calls) MachineInstr *EmitStartPt; public: - /// getLastLocalValue - Return the position of the last instruction - /// emitted for materializing constants for use in the current block. + /// 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. + /// Update the position of the last instruction emitted for materializing + /// constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// startNewBlock - Set the current block to which generated machine - /// instructions will be appended, and clear the local CSE map. - /// + /// 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. + /// Return current debug location information. DebugLoc getCurDebugLoc() const { return DL; } - /// LowerArguments - Do "fast" instruction selection for function arguments - /// and append machine instructions to the current block. Return true if - /// it is successful. + /// Do "fast" instruction selection for function arguments and append machine + /// instructions to the current block. Return true if it is successful. bool LowerArguments(); - /// 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. - /// + /// 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. - /// + /// 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. + /// 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. + /// 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. + /// 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); - /// \brief We're checking to see if we can fold \p LI into \p FoldInst. - /// Note that we could have a sequence where multiple LLVM IR instructions - /// are folded into the same machineinstr. For example we could have: + /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note + /// that we could have a sequence where multiple LLVM IR instructions are + /// folded into the same machineinstr. For example we could have: + /// /// A: x = load i32 *P /// B: y = icmp A, 42 /// C: br y, ... /// - /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know - /// about "B" (and any other folded instructions) because it is between - /// A and C. + /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know about "B" + /// (and any other folded instructions) because it is between A and C. /// /// If we succeed folding, return true. - /// bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); - /// \brief 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 + /// \brief 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. + /// /// This method should be implemented by targets. virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/, const LoadInst * /*LI*/) { return false; } - /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions - /// into the current block. + /// Reset InsertPt to prepare for inserting instructions into the current + /// block. void recomputeInsertPt(); - /// removeDeadCode - Remove all dead instructions between the I and E. + /// Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -161,11 +153,11 @@ public: DebugLoc DL; }; - /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions - /// into the local value area and return the old insert position. + /// 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. + /// Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); virtual ~FastISel(); @@ -174,69 +166,59 @@ protected: explicit FastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo); - /// 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. - /// + /// 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; - /// FastLowerArguments - This method is called by target-independent code to - /// do target specific argument lowering. It returns true if it was - /// successful. + /// This method is called by target-independent code to do target specific + /// argument lowering. It returns true if it was successful. virtual bool FastLowerArguments(); - /// FastEmit_r - This method is called by target-independent code - /// to request that an instruction with the given type and opcode - /// be emitted. + /// 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. - /// + /// 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. - /// + /// 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. - /// + /// 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. - /// + /// 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. - /// + /// 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, @@ -244,142 +226,130 @@ protected: 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. + /// \brief 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_i - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// immediate operand be emitted. + /// 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. + /// 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. - /// + /// 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. - /// + /// 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. - /// + /// 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_rrr - Emit a MachineInstr with three register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with three register operands and a result register in + /// the given register class. unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill); - /// FastEmitInst_ri - Emit a MachineInstr with a register operand, - /// an immediate, and a result register in the given register class. - /// + /// Emit a MachineInstr with a register operand, an immediate, 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_rii - Emit a MachineInstr with one register operand - /// and two immediate operands. - /// + /// Emit a MachineInstr with one register operand and two immediate operands. unsigned FastEmitInst_rii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_rf - Emit a MachineInstr with two register operands - /// and a result register in the given register class. - /// + /// 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. - /// + /// 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_rrii - Emit a MachineInstr with two register operands, - /// two immediates operands, and a result register in the given register - /// class. + /// Emit a MachineInstr with two register operands, two immediates operands, + /// and a result register in the given register class. unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_i - Emit a MachineInstr with a single immediate - /// operand, and a result register in the given register class. + /// 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_ii - Emit a MachineInstr with a two immediate operands. + /// Emit a MachineInstr with a two immediate operands. unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg - /// from a specified index of a superregister to a specified type. + /// 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. + /// 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. + /// 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); void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1); unsigned createResultReg(const TargetRegisterClass *RC); - /// TargetMaterializeConstant - Emit a constant in a register using - /// target-specific logic, such as constant pool loads. + /// 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. + /// Emit an alloca address in a register using target-specific logic. virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { return 0; } @@ -388,6 +358,15 @@ protected: return 0; } + /// \brief Check if \c Add is an add that can be safely folded into \c GEP. + /// + /// \c Add can be folded into \c GEP if: + /// - \c Add is an add, + /// - \c Add's size matches \c GEP's, + /// - \c Add is in the same basic block as \c GEP, and + /// - \c Add has a constant operand. + bool canFoldAddIntoGEP(const User *GEP, const Value *Add); + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); @@ -405,25 +384,26 @@ private: bool SelectInsertValue(const User *I); - /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. + /// \brief 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. + /// 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. + /// 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); - /// flushLocalValueMap - clears LocalValueMap and moves the area for the - /// new local variables to the beginning of the block. It helps to avoid - /// spilling cached variables across heavy instructions like calls. + /// Clears LocalValueMap and moves the area for the new local variables to the + /// beginning of the block. It helps to avoid spilling cached variables across + /// heavy instructions like calls. void flushLocalValueMap(); - /// hasTrivialKill - Test whether the given value has exactly one use. + /// Test whether the given value has exactly one use. bool hasTrivialKill(const Value *V) const; }; diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index ea6cb27b7b136..50d320f8e839d 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -49,8 +49,8 @@ class Value; /// function that is used when lowering a region of the function. /// class FunctionLoweringInfo { + const TargetMachine &TM; public: - const TargetLowering &TLI; const Function *Fn; MachineFunction *MF; MachineRegisterInfo *RegInfo; @@ -115,7 +115,12 @@ public: /// there's no other convenient place for it to live right now. std::vector > PHINodesToUpdate; - explicit FunctionLoweringInfo(const TargetLowering &TLI); + /// If the current MBB is a landing pad, the exception pointer and exception + /// selector registers are copied into these virtual registers by + /// SelectionDAGISel::PrepareEHLandingPad(). + unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; + + explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {} /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 0fd211b4a8656..48a0523dc6189 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -77,18 +77,6 @@ namespace ISD { /// 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 @@ -431,6 +419,10 @@ namespace ISD { /// getNode(). BITCAST, + /// ADDRSPACECAST - This operator converts between pointers of different + /// address spaces. + ADDRSPACECAST, + /// 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 @@ -452,11 +444,11 @@ namespace ISD { /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, - /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary + /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, 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, + FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -616,11 +608,17 @@ namespace ISD { ATOMIC_STORE, /// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmpLo, cmpHi, + /// swapLo, swapHi) /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amtLo, amtHi) + /// ValLo, ValHi, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amtLo, amtHi) /// These correspond to the atomicrmw instruction. ATOMIC_SWAP, ATOMIC_LOAD_ADD, @@ -647,7 +645,7 @@ namespace ISD { /// 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; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index ff65db4ee4ce9..26563a605574d 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -141,8 +141,8 @@ private: DenseMap AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing - /// a function. - SmallVectorAbstractScopesList; + /// a function. + SmallVector AbstractScopesList; /// CurrentFnLexicalScope - Top level scope for the current function. /// @@ -166,13 +166,13 @@ public: virtual ~LexicalScope() {} // Accessors. - LexicalScope *getParent() const { return Parent; } - const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } - bool isAbstractScope() const { return AbstractScope; } - SmallVector &getChildren() { return Children; } - SmallVector &getRanges() { return Ranges; } + LexicalScope *getParent() const { return Parent; } + const MDNode *getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + bool isAbstractScope() const { return AbstractScope; } + SmallVectorImpl &getChildren() { return Children; } + SmallVectorImpl &getRanges() { return Ranges; } /// addChild - Add a child scope. void addChild(LexicalScope *S) { Children.push_back(S); } diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index cb09a49666387..3a9fef6fbd781 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -9,12 +9,12 @@ // // 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 +// live range 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. +// that v is live at i'. In this implementation ranges can have holes, +// i.e. a range might look like [1,20), [50,65), [1000,1001). Each +// individual segment is represented as an instance of LiveRange::Segment, +// and the whole range is represented as an instance of LiveRange. // //===----------------------------------------------------------------------===// @@ -35,6 +35,7 @@ namespace llvm { class MachineRegisterInfo; class TargetRegisterInfo; class raw_ostream; + template class SmallPtrSet; /// VNInfo - Value Number Information. /// This class holds information about a machine level values, including @@ -66,7 +67,7 @@ namespace llvm { } /// Returns true if this value is defined by a PHI instruction (or was, - /// PHI instrucions may have been eliminated). + /// PHI instructions may have been eliminated). /// PHI-defs begin at a block boundary, all other defs begin at register or /// EC slots. bool isPHIDef() const { return def.isBlock(); } @@ -78,107 +79,136 @@ namespace llvm { void markUnused() { def = SlotIndex(); } }; - /// 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. + /// Result of a LiveRange query. This class hides the implementation details + /// of live ranges, and it should be used as the primary interface for + /// examining live ranges around instructions. + class LiveQueryResult { + VNInfo *const EarlyVal; + VNInfo *const LateVal; + const SlotIndex EndPoint; + const bool Kill; - LiveRange() : valno(0) {} + public: + LiveQueryResult(VNInfo *EarlyVal, VNInfo *LateVal, SlotIndex EndPoint, + bool Kill) + : EarlyVal(EarlyVal), LateVal(LateVal), EndPoint(EndPoint), Kill(Kill) + {} - LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) - : start(S), end(E), valno(V) { - assert(S < E && "Cannot create empty or backwards range"); + /// Return the value that is live-in to the instruction. This is the value + /// that will be read by the instruction's use operands. Return NULL if no + /// value is live-in. + VNInfo *valueIn() const { + return EarlyVal; } - /// contains - Return true if the index is covered by this range. - /// - bool contains(SlotIndex I) const { - return start <= I && I < end; + /// Return true if the live-in value is killed by this instruction. This + /// means that either the live range ends at the instruction, or it changes + /// value. + bool isKill() const { + return Kill; } - /// 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); + /// Return true if this instruction has a dead def. + bool isDeadDef() const { + return EndPoint.isDead(); } - bool operator<(const LiveRange &LR) const { - return start < LR.start || (start == LR.start && end < LR.end); + /// Return the value leaving the instruction, if any. This can be a + /// live-through value, or a live def. A dead def returns NULL. + VNInfo *valueOut() const { + return isDeadDef() ? 0 : LateVal; } - bool operator==(const LiveRange &LR) const { - return start == LR.start && end == LR.end; + + /// Return the value defined by this instruction, if any. This includes + /// dead defs, it is the value created by the instruction's def operands. + VNInfo *valueDefined() const { + return EarlyVal == LateVal ? 0 : LateVal; } - void dump() const; - void print(raw_ostream &os) const; + /// Return the end point of the last live range segment to interact with + /// the instruction, if any. + /// + /// The end point is an invalid SlotIndex only if the live range doesn't + /// intersect the instruction at all. + /// + /// The end point may be at or past the end of the instruction's basic + /// block. That means the value was live out of the block. + SlotIndex endPoint() const { + return EndPoint; + } }; - template <> struct isPodLike { static const bool value = true; }; - - raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); - + /// This class represents the liveness of a register, stack slot, etc. + /// It manages an ordered list of Segment objects. + /// The Segments are organized in a static single assignment form: At places + /// where a new value is defined or different values reach a CFG join a new + /// segment with a new value number is used. + class LiveRange { + public: - inline bool operator<(SlotIndex V, const LiveRange &LR) { - return V < LR.start; - } + /// This represents a simple continuous liveness interval for a value. + /// The start point is inclusive, the end point exclusive. These intervals + /// are rendered as [start,end). + struct Segment { + 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 segment. - inline bool operator<(const LiveRange &LR, SlotIndex V) { - return LR.start < V; - } + Segment() : valno(0) {} - /// 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: + Segment(SlotIndex S, SlotIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + assert(S < E && "Cannot create empty or backwards segment"); + } - typedef SmallVector Ranges; - typedef SmallVector VNInfoList; + /// Return true if the index is covered by this segment. + bool contains(SlotIndex I) const { + return start <= I && I < end; + } - 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 + /// Return true if the given interval, [S, E), is covered by this segment. + bool containsInterval(SlotIndex S, SlotIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } - struct InstrSlots { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4 - }; + bool operator<(const Segment &Other) const { + return start < Other.start || (start == Other.start && end < Other.end); + } + bool operator==(const Segment &Other) const { + return start == Other.start && end == Other.end; + } + void dump() const; }; - LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + typedef SmallVector Segments; + typedef SmallVector VNInfoList; + + Segments segments; // the liveness segments + VNInfoList valnos; // value#'s - typedef Ranges::iterator iterator; - iterator begin() { return ranges.begin(); } - iterator end() { return ranges.end(); } + typedef Segments::iterator iterator; + iterator begin() { return segments.begin(); } + iterator end() { return segments.end(); } - typedef Ranges::const_iterator const_iterator; - const_iterator begin() const { return ranges.begin(); } - const_iterator end() const { return ranges.end(); } + typedef Segments::const_iterator const_iterator; + const_iterator begin() const { return segments.begin(); } + const_iterator end() const { return segments.end(); } typedef VNInfoList::iterator vni_iterator; vni_iterator vni_begin() { return valnos.begin(); } - vni_iterator vni_end() { return valnos.end(); } + 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(); } + const_vni_iterator vni_end() const { return valnos.end(); } - /// advanceTo - Advance the specified iterator to point to the LiveRange + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the - /// end of the interval. If no LiveRange contains this position, but the + /// end of the range. If no Segment contains this position, but the /// position is in a hole, this method returns an iterator pointing to the - /// LiveRange immediately after the hole. + /// Segment immediately after the hole. iterator advanceTo(iterator I, SlotIndex Pos) { assert(I != end()); if (Pos >= endIndex()) @@ -187,22 +217,26 @@ namespace llvm { return I; } - /// find - Return an iterator pointing to the first range that ends after + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster - /// when searching large intervals. + /// when searching large ranges. /// - /// 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 contained in a Segment, that segment is returned. + /// If Pos is in a hole, the following Segment 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); + return const_cast(this)->find(Pos); } void clear() { valnos.clear(); - ranges.clear(); + segments.clear(); + } + + size_t size() const { + return segments.size(); } bool hasAtLeastOneValue() const { return !valnos.empty(); } @@ -220,7 +254,7 @@ namespace llvm { return valnos[ValNo]; } - /// containsValue - Returns true if VNI belongs to this interval. + /// containsValue - Returns true if VNI belongs to this range. bool containsValue(const VNInfo *VNI) const { return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id); } @@ -234,7 +268,7 @@ namespace llvm { return VNI; } - /// createDeadDef - Make sure the interval has a value defined at Def. + /// createDeadDef - Make sure the range has a value defined at Def. /// If one already exists, return it. Otherwise allocate a new value and /// add liveness for a dead def. VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator); @@ -251,42 +285,42 @@ namespace llvm { /// RenumberValues - Renumber all values in order of appearance and remove /// unused values. - void RenumberValues(LiveIntervals &lis); + void RenumberValues(); - /// MergeValueNumberInto - This method is called when two value nubmers + /// MergeValueNumberInto - This method is called when two value numbers /// are found to be equivalent. This eliminates V1, replacing all - /// LiveRanges with the V1 value number with the V2 value number. This can + /// segments 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 + /// Merge all of the live segments of a specific val# in RHS into this live + /// range as the specified value number. The segments in RHS are allowed + /// to overlap with segments in the current range, it will replace the + /// value numbers of the overlaped live segments with the specified value + /// number. + void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the segments of a specific val# + /// in RHS into this live range as the specified value number. + /// The segments in RHS are allowed to overlap with segments in the + /// current range, but only if the overlapping segments have the /// specified value number. - void MergeValueInAsValue(const LiveInterval &RHS, + void MergeValueInAsValue(const LiveRange &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo); - bool empty() const { return ranges.empty(); } + bool empty() const { return segments.empty(); } - /// beginIndex - Return the lowest numbered slot covered by interval. + /// beginIndex - Return the lowest numbered slot covered. SlotIndex beginIndex() const { - assert(!empty() && "Call to beginIndex() on empty interval."); - return ranges.front().start; + assert(!empty() && "Call to beginIndex() on empty range."); + return segments.front().start; } - /// endNumber - return the maximum point of the interval of the whole, + /// endNumber - return the maximum point of the range of the whole, /// exclusive. SlotIndex endIndex() const { - assert(!empty() && "Call to endIndex() on empty interval."); - return ranges.back().end; + assert(!empty() && "Call to endIndex() on empty range."); + return segments.back().end; } bool expiredAt(SlotIndex index) const { @@ -298,31 +332,23 @@ namespace llvm { 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.getRegSlot(true)); - return r != end() && r->end == index; - } - - /// 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 the segment that contains the specified index, or null if there + /// is none. + const Segment *getSegmentContaining(SlotIndex Idx) const { + const_iterator I = FindSegmentContaining(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 the live segment that contains the specified index, or null if + /// there is none. + Segment *getSegmentContaining(SlotIndex Idx) { + iterator I = FindSegmentContaining(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); + const_iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : I->valno; } @@ -330,76 +356,68 @@ namespace llvm { /// necessarilly including Idx, or NULL. Use this to find the reaching def /// used by an instruction at this SlotIndex position. VNInfo *getVNInfoBefore(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx.getPrevSlot()); + const_iterator I = FindSegmentContaining(Idx.getPrevSlot()); 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) { + /// Return an iterator to the segment that contains the specified index, or + /// end() if there is none. + iterator FindSegmentContaining(SlotIndex Idx) { iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - const_iterator FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator FindSegmentContaining(SlotIndex Idx) const { const_iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - /// overlaps - Return true if the intersection of the two live intervals is + /// overlaps - Return true if the intersection of the two live ranges is /// not empty. - bool overlaps(const LiveInterval& other) const { + bool overlaps(const LiveRange &other) const { if (other.empty()) return false; return overlapsFrom(other, other.begin()); } - /// overlaps - Return true if the two intervals have overlapping segments + /// overlaps - Return true if the two ranges have overlapping segments /// that are not coalescable according to CP. /// - /// Overlapping segments where one interval is defined by a coalescable + /// Overlapping segments where one range is defined by a coalescable /// copy are allowed. - bool overlaps(const LiveInterval &Other, const CoalescerPair &CP, + bool overlaps(const LiveRange &Other, const CoalescerPair &CP, const SlotIndexes&) const; - /// overlaps - Return true if the live interval overlaps a range specified + /// overlaps - Return true if the live range overlaps an interval specified /// by [Start, End). bool overlaps(SlotIndex Start, SlotIndex End) const; - /// overlapsFrom - Return true if the intersection of the two live intervals + /// overlapsFrom - Return true if the intersection of the two live ranges /// 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; + /// scanning the Other range starting at I. + bool overlapsFrom(const LiveRange &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. - iterator addRange(LiveRange LR) { - return addRangeFrom(LR, ranges.begin()); + /// Add the specified Segment to this range, merging segments as + /// appropriate. This returns an iterator to the inserted segment (which + /// may have grown since it was inserted). + iterator addSegment(Segment S) { + return addSegmentFrom(S, segments.begin()); } - /// extendInBlock - If this interval is live before Kill in the basic block + /// extendInBlock - If this range is live before Kill in the basic block /// that starts at StartIdx, extend it to be live up to Kill, and return - /// the value. If there is no live range before Kill, return NULL. + /// the value. If there is no segment before Kill, return NULL. VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); - /// 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, + /// join - Join two live ranges (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS ranges as specified. If + /// the ranges are not joinable, this aborts. + void join(LiveRange &Other, const int *ValNoAssignments, const int *RHSValNoAssignments, - SmallVector &NewVNInfo, - MachineRegisterInfo *MRI); + SmallVectorImpl &NewVNInfo); - /// 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); - } - - /// True iff this live range is a single segment that lies between the + /// True iff this segment is a single segment that lies between the /// specified boundaries, exclusively. Vregs live across a backedge are not /// considered local. The boundaries are expected to lie within an extended /// basic block, so vregs that are not live out should contain no holes. @@ -408,25 +426,63 @@ namespace llvm { endIndex() < End.getBoundaryIndex(); } - /// 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); + /// Remove the specified segment from this range. Note that the segment + /// must be a single Segment in its entirety. + void removeSegment(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo = false); - void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { - removeRange(LR.start, LR.end, RemoveDeadValNo); + void removeSegment(Segment S, bool RemoveDeadValNo = false) { + removeSegment(S.start, S.end, RemoveDeadValNo); } - /// removeValNo - Remove all the ranges defined by the specified value#. + /// Query Liveness at Idx. + /// The sub-instruction slot of Idx doesn't matter, only the instruction + /// it refers to is considered. + LiveQueryResult Query(SlotIndex Idx) const { + // Find the segment that enters the instruction. + const_iterator I = find(Idx.getBaseIndex()); + const_iterator E = end(); + if (I == E) + return LiveQueryResult(0, 0, SlotIndex(), false); + + // Is this an instruction live-in segment? + // If Idx is the start index of a basic block, include live-in segments + // that start at Idx.getBaseIndex(). + VNInfo *EarlyVal = 0; + VNInfo *LateVal = 0; + SlotIndex EndPoint; + bool Kill = false; + if (I->start <= Idx.getBaseIndex()) { + EarlyVal = I->valno; + EndPoint = I->end; + // Move to the potentially live-out segment. + if (SlotIndex::isSameInstr(Idx, I->end)) { + Kill = true; + if (++I == E) + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + // Special case: A PHIDef value can have its def in the middle of a + // segment if the value happens to be live out of the layout + // predecessor. + // Such a value is not live-in. + if (EarlyVal->def == Idx.getBaseIndex()) + EarlyVal = 0; + } + // I now points to the segment that may be live-through, or defined by + // this instr. Ignore segments starting after the current instr. + if (!SlotIndex::isEarlierInstr(Idx, I->start)) { + LateVal = I->valno; + EndPoint = I->end; + } + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + + /// removeValNo - Remove all the segments 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. + /// Returns true if the live range is zero length, i.e. no live segments + /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { for (const_iterator i = begin(), e = end(); i != e; ++i) if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < @@ -435,27 +491,16 @@ namespace llvm { 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; - } - - bool operator<(const LiveInterval& other) const { + bool operator<(const LiveRange& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); - return (thisIndex < otherIndex || - (thisIndex == otherIndex && reg < other.reg)); + return thisIndex < otherIndex; } void print(raw_ostream &OS) const; void dump() const; - /// \brief Walk the interval and assert if any invariants fail to hold. + /// \brief Walk the range and assert if any invariants fail to hold. /// /// Note that this is a no-op when asserts are disabled. #ifdef NDEBUG @@ -466,11 +511,55 @@ namespace llvm { private: - Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); - void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); - Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); + iterator addSegmentFrom(Segment S, iterator From); + void extendSegmentEndTo(iterator I, SlotIndex NewEnd); + iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); void markValNoForDeletion(VNInfo *V); + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveRange &LR) { + LR.print(OS); + return OS; + } + + /// LiveInterval - This class represents the liveness of a register, + /// or stack slot. + class LiveInterval : public LiveRange { + public: + typedef LiveRange super; + + const unsigned reg; // the register or stack slot of this interval. + float weight; // weight of this interval + + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), weight(Weight) {} + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + /// isSpillable - Can this interval be spilled? + bool isSpillable() const { + return weight != llvm::huge_valf; + } + + /// markNotSpillable - Mark interval as not spillable + void markNotSpillable() { + weight = llvm::huge_valf; + } + + 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; + void dump() const; + + private: LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; }; @@ -480,54 +569,65 @@ namespace llvm { return OS; } - /// Helper class for performant LiveInterval bulk updates. + raw_ostream &operator<<(raw_ostream &OS, const LiveRange::Segment &S); + + inline bool operator<(SlotIndex V, const LiveRange::Segment &S) { + return V < S.start; + } + + inline bool operator<(const LiveRange::Segment &S, SlotIndex V) { + return S.start < V; + } + + /// Helper class for performant LiveRange bulk updates. /// - /// Calling LiveInterval::addRange() repeatedly can be expensive on large + /// Calling LiveRange::addSegment() repeatedly can be expensive on large /// live ranges because segments after the insertion point may need to be /// shifted. The LiveRangeUpdater class can defer the shifting when adding /// many segments in order. /// - /// The LiveInterval will be in an invalid state until flush() is called. + /// The LiveRange will be in an invalid state until flush() is called. class LiveRangeUpdater { - LiveInterval *LI; + LiveRange *LR; SlotIndex LastStart; - LiveInterval::iterator WriteI; - LiveInterval::iterator ReadI; - SmallVector Spills; + LiveRange::iterator WriteI; + LiveRange::iterator ReadI; + SmallVector Spills; void mergeSpills(); public: - /// Create a LiveRangeUpdater for adding segments to LI. - /// LI will temporarily be in an invalid state until flush() is called. - LiveRangeUpdater(LiveInterval *li = 0) : LI(li) {} + /// Create a LiveRangeUpdater for adding segments to LR. + /// LR will temporarily be in an invalid state until flush() is called. + LiveRangeUpdater(LiveRange *lr = 0) : LR(lr) {} ~LiveRangeUpdater() { flush(); } - /// Add a segment to LI and coalesce when possible, just like LI.addRange(). - /// Segments should be added in increasing start order for best performance. - void add(LiveRange); + /// Add a segment to LR and coalesce when possible, just like + /// LR.addSegment(). Segments should be added in increasing start order for + /// best performance. + void add(LiveRange::Segment); void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) { - add(LiveRange(Start, End, VNI)); + add(LiveRange::Segment(Start, End, VNI)); } - /// Return true if the LI is currently in an invalid state, and flush() + /// Return true if the LR is currently in an invalid state, and flush() /// needs to be called. bool isDirty() const { return LastStart.isValid(); } - /// Flush the updater state to LI so it is valid and contains all added + /// Flush the updater state to LR so it is valid and contains all added /// segments. void flush(); /// Select a different destination live range. - void setDest(LiveInterval *li) { - if (LI != li && isDirty()) + void setDest(LiveRange *lr) { + if (LR != lr && isDirty()) flush(); - LI = li; + LR = lr; } /// Get the current destination live range. - LiveInterval *getDest() const { return LI; } + LiveRange *getDest() const { return LR; } void dump() const; void print(raw_ostream&) const; @@ -538,99 +638,6 @@ namespace llvm { return OS; } - /// LiveRangeQuery - Query information about a live range around a given - /// instruction. This class hides the implementation details of live ranges, - /// and it should be used as the primary interface for examining live ranges - /// around instructions. - /// - class LiveRangeQuery { - VNInfo *EarlyVal; - VNInfo *LateVal; - SlotIndex EndPoint; - bool Kill; - - public: - /// Create a LiveRangeQuery for the given live range and instruction index. - /// The sub-instruction slot of Idx doesn't matter, only the instruction it - /// refers to is considered. - LiveRangeQuery(const LiveInterval &LI, SlotIndex Idx) - : EarlyVal(0), LateVal(0), Kill(false) { - // Find the segment that enters the instruction. - LiveInterval::const_iterator I = LI.find(Idx.getBaseIndex()); - LiveInterval::const_iterator E = LI.end(); - if (I == E) - return; - // Is this an instruction live-in segment? - // If Idx is the start index of a basic block, include live-in segments - // that start at Idx.getBaseIndex(). - if (I->start <= Idx.getBaseIndex()) { - EarlyVal = I->valno; - EndPoint = I->end; - // Move to the potentially live-out segment. - if (SlotIndex::isSameInstr(Idx, I->end)) { - Kill = true; - if (++I == E) - return; - } - // Special case: A PHIDef value can have its def in the middle of a - // segment if the value happens to be live out of the layout - // predecessor. - // Such a value is not live-in. - if (EarlyVal->def == Idx.getBaseIndex()) - EarlyVal = 0; - } - // I now points to the segment that may be live-through, or defined by - // this instr. Ignore segments starting after the current instr. - if (SlotIndex::isEarlierInstr(Idx, I->start)) - return; - LateVal = I->valno; - EndPoint = I->end; - } - - /// Return the value that is live-in to the instruction. This is the value - /// that will be read by the instruction's use operands. Return NULL if no - /// value is live-in. - VNInfo *valueIn() const { - return EarlyVal; - } - - /// Return true if the live-in value is killed by this instruction. This - /// means that either the live range ends at the instruction, or it changes - /// value. - bool isKill() const { - return Kill; - } - - /// Return true if this instruction has a dead def. - bool isDeadDef() const { - return EndPoint.isDead(); - } - - /// Return the value leaving the instruction, if any. This can be a - /// live-through value, or a live def. A dead def returns NULL. - VNInfo *valueOut() const { - return isDeadDef() ? 0 : LateVal; - } - - /// Return the value defined by this instruction, if any. This includes - /// dead defs, it is the value created by the instruction's def operands. - VNInfo *valueDefined() const { - return EarlyVal == LateVal ? 0 : LateVal; - } - - /// Return the end point of the last live range segment to interact with - /// the instruction, if any. - /// - /// The end point is an invalid SlotIndex only if the live range doesn't - /// intersect the instruction at all. - /// - /// The end point may be at or past the end of the instruction's basic - /// block. That means the value was live out of the block. - SlotIndex endPoint() const { - return EndPoint; - } - }; - /// 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 diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 7d72f37255b4c..d8437f09aaa7a 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -35,6 +35,7 @@ namespace llvm { class AliasAnalysis; class BitVector; + class BlockFrequency; class LiveRangeCalc; class LiveVariables; class MachineDominatorTree; @@ -89,9 +90,9 @@ namespace llvm { /// block. SmallVector, 8> RegMaskBlocks; - /// RegUnitIntervals - Keep a live interval for each register unit as a way - /// of tracking fixed physreg interference. - SmallVector RegUnitIntervals; + /// Keeps a live range set for each register unit to track fixed physreg + /// interference. + SmallVector RegUnitRanges; public: static char ID; // Pass identification, replacement for typeid @@ -99,12 +100,13 @@ namespace llvm { virtual ~LiveIntervals(); // Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); + static float getSpillWeight(bool isDef, bool isUse, BlockFrequency freq); LiveInterval &getInterval(unsigned Reg) { - LiveInterval *LI = VirtRegIntervals[Reg]; - assert(LI && "Interval does not exist for virtual register"); - return *LI; + if (hasInterval(Reg)) + return *VirtRegIntervals[Reg]; + else + return createAndComputeVirtRegInterval(Reg); } const LiveInterval &getInterval(unsigned Reg) const { @@ -116,12 +118,17 @@ namespace llvm { } // Interval creation. - LiveInterval &getOrCreateInterval(unsigned Reg) { - if (!hasInterval(Reg)) { - VirtRegIntervals.grow(Reg); - VirtRegIntervals[Reg] = createInterval(Reg); - } - return getInterval(Reg); + LiveInterval &createEmptyInterval(unsigned Reg) { + assert(!hasInterval(Reg) && "Interval already exists!"); + VirtRegIntervals.grow(Reg); + VirtRegIntervals[Reg] = createInterval(Reg); + return *VirtRegIntervals[Reg]; + } + + LiveInterval &createAndComputeVirtRegInterval(unsigned Reg) { + LiveInterval &LI = createEmptyInterval(Reg); + computeVirtRegInterval(LI); + return LI; } // Interval removal. @@ -130,10 +137,10 @@ namespace llvm { VirtRegIntervals[Reg] = 0; } - /// 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); + /// Given a register and an instruction, adds a live segment from that + /// instruction to the end of its MBB. + LiveInterval::Segment addSegmentToEndOfBlock(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 @@ -153,7 +160,7 @@ namespace llvm { /// extended to be live out of the basic block. /// /// See also LiveRangeCalc::extend(). - void extendToIndices(LiveInterval *LI, ArrayRef Indices); + void extendToIndices(LiveRange &LR, ArrayRef Indices); /// pruneValue - If an LI value is live at Kill, prune its live range by /// removing any liveness reachable from Kill. Add live range end points to @@ -199,14 +206,14 @@ namespace llvm { return Indexes->getMBBEndIdx(mbb); } - bool isLiveInToMBB(const LiveInterval &li, + bool isLiveInToMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBStartIdx(mbb)); + return LR.liveAt(getMBBStartIdx(mbb)); } - bool isLiveOutOfMBB(const LiveInterval &li, + bool isLiveOutOfMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBEndIdx(mbb).getPrevSlot()); + return LR.liveAt(getMBBEndIdx(mbb).getPrevSlot()); } MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { @@ -224,6 +231,12 @@ namespace llvm { return Indexes->insertMachineInstrInMaps(MI); } + void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B, + MachineBasicBlock::iterator E) { + for (MachineBasicBlock::iterator I = B; I != E; ++I) + Indexes->insertMachineInstrInMaps(I); + } + void RemoveMachineInstrFromMaps(MachineInstr *MI) { Indexes->removeMachineInstrFromMaps(MI); } @@ -351,24 +364,24 @@ namespace llvm { /// getRegUnit - Return the live range for Unit. /// It will be computed if it doesn't exist. - LiveInterval &getRegUnit(unsigned Unit) { - LiveInterval *LI = RegUnitIntervals[Unit]; - if (!LI) { + LiveRange &getRegUnit(unsigned Unit) { + LiveRange *LR = RegUnitRanges[Unit]; + if (!LR) { // Compute missing ranges on demand. - RegUnitIntervals[Unit] = LI = new LiveInterval(Unit, HUGE_VALF); - computeRegUnitInterval(LI); + RegUnitRanges[Unit] = LR = new LiveRange(); + computeRegUnitRange(*LR, Unit); } - return *LI; + return *LR; } /// getCachedRegUnit - Return the live range for Unit if it has already /// been computed, or NULL if it hasn't been computed yet. - LiveInterval *getCachedRegUnit(unsigned Unit) { - return RegUnitIntervals[Unit]; + LiveRange *getCachedRegUnit(unsigned Unit) { + return RegUnitRanges[Unit]; } - const LiveInterval *getCachedRegUnit(unsigned Unit) const { - return RegUnitIntervals[Unit]; + const LiveRange *getCachedRegUnit(unsigned Unit) const { + return RegUnitRanges[Unit]; } private: @@ -384,8 +397,8 @@ namespace llvm { void dumpInstrs() const; void computeLiveInRegUnits(); - void computeRegUnitInterval(LiveInterval*); - void computeVirtRegInterval(LiveInterval*); + void computeRegUnitRange(LiveRange&, unsigned Unit); + void computeVirtRegInterval(LiveInterval&); class HMEditor; }; diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 615b339bd79cc..95933d11dbb3a 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -32,7 +32,7 @@ typedef SparseBitVector<128> LiveVirtRegBitSet; /// Compare a live virtual register segment to a LiveIntervalUnion segment. inline bool -overlap(const LiveRange &VRSeg, +overlap(const LiveInterval::Segment &VRSeg, const IntervalMap::const_iterator &LUSeg) { return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; } diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index e59276fd6d95d..7edf67cc24d1a 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -19,19 +19,21 @@ #define LLVM_CODEGEN_LIVERANGEEDIT_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" namespace llvm { class AliasAnalysis; class LiveIntervals; +class MachineBlockFrequencyInfo; class MachineLoopInfo; -class MachineRegisterInfo; class VirtRegMap; -class LiveRangeEdit { +class LiveRangeEdit : private MachineRegisterInfo::Delegate { public: /// Callback methods for LiveRangeEdit owners. class Delegate { @@ -56,7 +58,7 @@ public: private: LiveInterval *Parent; - SmallVectorImpl &NewRegs; + SmallVectorImpl &NewRegs; MachineRegisterInfo &MRI; LiveIntervals &LIS; VirtRegMap *VRM; @@ -89,6 +91,16 @@ private: /// a load, eliminate the register by folding the def into the use. bool foldAsLoad(LiveInterval *LI, SmallVectorImpl &Dead); + typedef SetVector, + SmallPtrSet > ToShrinkSet; + /// Helper for eliminateDeadDefs. + void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink); + + /// MachineRegisterInfo callback to notify when new virtual + /// registers are created. + void MRI_NoteNewVirtualRegister(unsigned VReg); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -100,7 +112,7 @@ public: /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. LiveRangeEdit(LiveInterval *parent, - SmallVectorImpl &newRegs, + SmallVectorImpl &newRegs, MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, @@ -110,7 +122,9 @@ public: TII(*MF.getTarget().getInstrInfo()), TheDelegate(delegate), FirstNew(newRegs.size()), - ScannedRemattable(false) {} + ScannedRemattable(false) { MRI.setDelegate(this); } + + ~LiveRangeEdit() { MRI.resetDelegate(this); } LiveInterval &getParent() const { assert(Parent && "No parent LiveInterval"); @@ -119,23 +133,30 @@ public: unsigned getReg() const { return getParent().reg; } /// Iterator for accessing the new registers added by this edit. - typedef SmallVectorImpl::const_iterator iterator; + 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]; } + unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; } - ArrayRef regs() const { + ArrayRef regs() const { return makeArrayRef(NewRegs).slice(FirstNew); } + /// createEmptyIntervalFrom - Create a new empty interval based on OldReg. + LiveInterval &createEmptyIntervalFrom(unsigned OldReg); + /// createFrom - Create a new virtual register based on OldReg. - LiveInterval &createFrom(unsigned OldReg); + unsigned createFrom(unsigned OldReg); /// create - Create a new register with the same class and original slot as /// parent. - LiveInterval &create() { + LiveInterval &createEmptyInterval() { + return createEmptyIntervalFrom(getReg()); + } + + unsigned create() { return createFrom(getReg()); } @@ -201,7 +222,8 @@ public: /// calculateRegClassAndHint - Recompute register class and hint for each new /// register. void calculateRegClassAndHint(MachineFunction&, - const MachineLoopInfo&); + const MachineLoopInfo&, + const MachineBlockFrequencyInfo&); }; } diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h new file mode 100644 index 0000000000000..02b9c55cc61f2 --- /dev/null +++ b/include/llvm/CodeGen/LiveRegUnits.h @@ -0,0 +1,88 @@ +//===-- llvm/CodeGen/LiveRegUnits.h - Live register unit 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 Set of live register units. This can be used for ad +// hoc liveness tracking after register allocation. You can start with the +// live-ins/live-outs at the beginning/end of a block and update the information +// while walking the instructions inside the block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEREGUNITS_H +#define LLVM_CODEGEN_LIVEREGUNITS_H + +#include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include + +namespace llvm { + +class MachineInstr; + +/// A set of live register units with functions to track liveness when walking +/// backward/forward through a basic block. +class LiveRegUnits { + SparseSet LiveUnits; + + LiveRegUnits(const LiveRegUnits&) LLVM_DELETED_FUNCTION; + LiveRegUnits &operator=(const LiveRegUnits&) LLVM_DELETED_FUNCTION; +public: + /// \brief Constructs a new empty LiveRegUnits set. + LiveRegUnits() {} + + void init(const TargetRegisterInfo *TRI) { + LiveUnits.clear(); + LiveUnits.setUniverse(TRI->getNumRegs()); + } + + void clear() { LiveUnits.clear(); } + + bool empty() const { return LiveUnits.empty(); } + + /// \brief Adds a register to the set. + void addReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.insert(*RUnits); + } + + /// \brief Removes a register from the set. + void removeReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.erase(*RUnits); + } + + /// \brief Removes registers clobbered by the regmask operand @p Op. + void removeRegsInMask(const MachineOperand &Op, const MCRegisterInfo &MCRI); + + /// \brief Returns true if register @p Reg (or one of its super register) is + /// contained in the set. + bool contains(unsigned Reg, const MCRegisterInfo &MCRI) const { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) { + if (LiveUnits.count(*RUnits)) + return true; + } + return false; + } + + /// \brief Simulates liveness when stepping backwards over an + /// instruction(bundle): Remove Defs, add uses. + void stepBackward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Simulates liveness when stepping forward over an + /// instruction(bundle): Remove killed-uses, add defs. + void stepForward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Adds all registers in the live-in list of block @p BB. + void addLiveIns(const MachineBasicBlock *MBB, const MCRegisterInfo &MCRI); +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 6628fd278e452..dc735f7b50b9a 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -157,8 +157,8 @@ private: // Intermediate data structures void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, - SmallVector &Defs); - void UpdatePhysRegDefs(MachineInstr *MI, SmallVector &Defs); + SmallVectorImpl &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl &Defs); /// FindLastRefOrPartRef - Return the last reference or partial reference of /// the specified register. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 0f2f8746b3825..7717809e0d9fc 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -296,6 +296,11 @@ public: /// is an error to add the same register to the same set more than once. void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + /// Add PhysReg as live in to this block, and ensure that there is a copy of + /// PhysReg to a virtual register of class RC. Return the virtual register + /// that is a copy of the live in PhysReg. + unsigned addLiveIn(unsigned PhysReg, const TargetRegisterClass *RC); + /// removeLiveIn - Remove the specified register from the live in set. /// void removeLiveIn(unsigned Reg); @@ -405,8 +410,8 @@ public: /// 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 + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode instruction. When adding instructions 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. @@ -728,6 +733,31 @@ template <> struct GraphTraits > { } }; + + +/// MachineInstrSpan provides an interface to get an iteration range +/// containing the instruction it was initialized with, along with all +/// those instructions inserted prior to or following that instruction +/// at some point after the MachineInstrSpan is constructed. +class MachineInstrSpan { + MachineBasicBlock &MBB; + MachineBasicBlock::iterator I, B, E; +public: + MachineInstrSpan(MachineBasicBlock::iterator I) + : MBB(*I->getParent()), + I(I), + B(I == MBB.begin() ? MBB.end() : llvm::prior(I)), + E(llvm::next(I)) {} + + MachineBasicBlock::iterator begin() { + return B == MBB.end() ? MBB.begin() : llvm::next(B); + } + MachineBasicBlock::iterator end() { return E; } + bool empty() { return begin() == end(); } + + MachineBasicBlock::iterator getInitial() { return I; } +}; + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 98dd03b45cf78..c59948fd654e8 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,4 +1,4 @@ -//==- MachineBranchProbabilityInfo.h - Machine Branch Probability Analysis -==// +//=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 8ed215d75bcf0..912ce89662685 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -132,15 +132,17 @@ public: /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const DataLayout *TD; ///< The machine's DataLayout. - unsigned PoolAlignment; ///< The alignment for the pool. + const TargetMachine &TM; ///< The target machine. + unsigned PoolAlignment; ///< The alignment for the pool. std::vector Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet MachineCPVsSharingEntries; + + const DataLayout *getDataLayout() const; public: /// @brief The only constructor. - explicit MachineConstantPool(const DataLayout *td) - : TD(td), PoolAlignment(1) {} + explicit MachineConstantPool(const TargetMachine &TM) + : TM(TM), PoolAlignment(1) {} ~MachineConstantPool(); /// getConstantPoolAlignment - Return the alignment required by diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index cdec7e663708a..022634df87cf5 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -27,6 +27,7 @@ class Type; class MachineFunction; class MachineBasicBlock; class TargetFrameLowering; +class TargetMachine; class BitVector; class Value; class AllocaInst; @@ -119,6 +120,8 @@ class MachineFrameInfo { isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {} }; + const TargetMachine &TM; + /// Objects - The list of stack objects allocated... /// std::vector Objects; @@ -201,10 +204,6 @@ class MachineFrameInfo { /// 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; @@ -223,9 +222,11 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; + + const TargetFrameLowering *getFrameLowering() const; public: - explicit MachineFrameInfo(const TargetFrameLowering &tfi, bool RealignOpt) - : TFI(tfi), RealignOption(RealignOpt) { + explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) + : TM(TM), RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 195cce7a64d75..cccab81efbb29 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -397,8 +397,8 @@ public: return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type); } - // 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 + /// 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(QueryType Type = AllInBundle) const { @@ -637,6 +637,13 @@ public: bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } + /// A DBG_VALUE is indirect iff the first operand is a register and + /// the second operand is an immediate. + bool isIndirectDebugValue() const { + return isDebugValue() + && getOperand(0).isReg() + && getOperand(1).isImm(); + } bool isPHI() const { return getOpcode() == TargetOpcode::PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } @@ -886,13 +893,12 @@ public: /// 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 addRegisterDead(unsigned Reg, 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); + void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = 0); /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. @@ -908,11 +914,6 @@ public: 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; - /// hasOrderedMemoryRef - Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 92c8da991ca44..df01371a47ec5 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -335,6 +335,51 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address. The convention is that a DBG_VALUE is indirect iff the +/// second operand is an immediate. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + if (IsIndirect) + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(MD); + else { + assert(Offset == 0 && "A direct address cannot have an offset."); + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(MD); + } +} + +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address and inserts it at position I. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD); + BB.insert(I, MI); + return MachineInstrBuilder(MF, MI); +} + + inline unsigned getDefRegState(bool B) { return B ? RegState::Define : 0; } diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index a3acec8095473..460c08c8ca7ee 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -106,9 +106,9 @@ class MachineModuleInfo : public ImmutablePass { /// 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; + /// List of moves done by a function's prolog. Used to construct frame maps + /// by debug and exception handling consumers. + std::vector FrameInstructions; /// CompactUnwindEncoding - If the target supports it, this is the compact /// unwind encoding. It replaces a function's CIE and FDE. @@ -231,10 +231,16 @@ public: UsesVAFloatArgument = b; } - /// getFrameMoves - Returns a reference to a list of moves done in the current + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. - std::vector &getFrameMoves() { return FrameMoves; } + const std::vector &getFrameInstructions() const { + return FrameInstructions; + } + + void addFrameInst(const MCCFIInstruction &Inst) { + FrameInstructions.push_back(Inst); + } /// getCompactUnwindEncoding - Returns the compact unwind encoding for a /// function if the target supports the encoding. This encoding replaces a diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 414770b9ecf0f..40f3580bfdb49 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -391,7 +391,7 @@ public: } void setIsDebug(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); IsDebug = Val; } @@ -564,6 +564,8 @@ public: unsigned SubReg = 0, bool isDebug = false, bool isInternalRead = false) { + assert(!(isDead && !isDef) && "Dead flag on non-def"); + assert(!(isKill && isDef) && "Kill flag on def"); MachineOperand Op(MachineOperand::MO_Register); Op.IsDef = isDef; Op.IsImp = isImp; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 24ba7bb1ac58e..58ca907316acc 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,16 +17,29 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include namespace llvm { +class PSetIterator; /// MachineRegisterInfo - Keep track of information for virtual and physical /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { - const TargetRegisterInfo *const TRI; +public: + class Delegate { + virtual void anchor(); + public: + virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0; + + virtual ~Delegate() {} + }; + +private: + const TargetMachine &TM; + Delegate *TheDelegate; /// IsSSA - True when the machine function is in SSA form and virtual /// registers have a single def. @@ -108,9 +121,30 @@ class MachineRegisterInfo { MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: - explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); + explicit MachineRegisterInfo(const TargetMachine &TM); ~MachineRegisterInfo(); + const TargetRegisterInfo *getTargetRegisterInfo() const { + return TM.getRegisterInfo(); + } + + void resetDelegate(Delegate *delegate) { + // Ensure another delegate does not take over unless the current + // delegate first unattaches itself. If we ever need to multicast + // notifications, we will need to change to using a list. + assert(TheDelegate == delegate && + "Only the current delegate can perform reset!"); + TheDelegate = 0; + } + + void setDelegate(Delegate *delegate) { + assert(delegate && !TheDelegate && + "Attempted to set delegate to null, or to change it without " + "first resetting it!"); + + TheDelegate = delegate; + } + //===--------------------------------------------------------------------===// // Function State //===--------------------------------------------------------------------===// @@ -294,6 +328,11 @@ public: /// a physreg. bool isConstantPhysReg(unsigned PhysReg, const MachineFunction &MF) const; + /// Get an iterator over the pressure sets affected by the given physical or + /// virtual register. If RegUnit is physical, it must be a register unit (from + /// MCRegUnitIterator). + PSetIterator getPressureSets(unsigned RegUnit) const; + //===--------------------------------------------------------------------===// // Virtual Register Info //===--------------------------------------------------------------------===// @@ -377,7 +416,8 @@ public: bool isPhysRegUsed(unsigned Reg) const { if (UsedPhysRegMask.test(Reg)) return true; - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) if (UsedRegUnits.test(*Units)) return true; return false; @@ -392,7 +432,8 @@ public: /// setPhysRegUsed - Mark the specified register used in this function. /// This should only be called during and after register allocation. void setPhysRegUsed(unsigned Reg) { - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.set(*Units); } @@ -406,7 +447,8 @@ public: /// This should only be called during and after register allocation. void setPhysRegUnused(unsigned Reg) { UsedPhysRegMask.reset(Reg); - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.reset(*Units); } @@ -466,7 +508,8 @@ public: /// register, so a register allocator needs to track its liveness and /// availability. bool isAllocatable(unsigned PhysReg) const { - return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); + return getTargetRegisterInfo()->isInAllocatableClass(PhysReg) && + !isReserved(PhysReg); } //===--------------------------------------------------------------------===// @@ -611,9 +654,49 @@ public: return Op->getParent(); } }; +}; +/// Iterate over the pressure sets affected by the given physical or virtual +/// register. If Reg is physical, it must be a register unit (from +/// MCRegUnitIterator). +class PSetIterator { + const int *PSet; + unsigned Weight; +public: + PSetIterator(): PSet(0), Weight(0) {} + PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { + const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); + if (TargetRegisterInfo::isVirtualRegister(RegUnit)) { + const TargetRegisterClass *RC = MRI->getRegClass(RegUnit); + PSet = TRI->getRegClassPressureSets(RC); + Weight = TRI->getRegClassWeight(RC).RegWeight; + } + else { + PSet = TRI->getRegUnitPressureSets(RegUnit); + Weight = TRI->getRegUnitWeight(RegUnit); + } + if (*PSet == -1) + PSet = 0; + } + bool isValid() const { return PSet; } + + unsigned getWeight() const { return Weight; } + + unsigned operator*() const { return *PSet; } + + void operator++() { + assert(isValid() && "Invalid PSetIterator."); + ++PSet; + if (*PSet == -1) + PSet = 0; + } }; +inline PSetIterator MachineRegisterInfo:: +getPressureSets(unsigned RegUnit) const { + return PSetIterator(RegUnit, this); +} + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h index 244b466e17282..e77845745165a 100644 --- a/include/llvm/CodeGen/MachineRelocation.h +++ b/include/llvm/CodeGen/MachineRelocation.h @@ -57,7 +57,7 @@ class MachineRelocation { 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 + MachineBasicBlock *MBB; // If this is a pointer to an 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 diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 769e4b42a5f16..77828953347c6 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -7,8 +7,48 @@ // //===----------------------------------------------------------------------===// // -// This file provides a MachineSchedRegistry for registering alternative machine -// schedulers. A Target may provide an alternative scheduler implementation by +// This file provides an interface for customizing the standard MachineScheduler +// pass. Note that the entire pass may be replaced as follows: +// +// TargetMachine::createPassConfig(PassManagerBase &PM) { +// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); +// ...} +// +// The MachineScheduler pass is only responsible for choosing the regions to be +// scheduled. Targets can override the DAG builder and scheduler without +// replacing the pass as follows: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new CustomMachineScheduler(C); +// } +// +// The default scheduler, ScheduleDAGMI, builds the DAG and drives list +// scheduling while updating the instruction stream, register pressure, and live +// intervals. Most targets don't need to override the DAG builder and list +// schedulier, but subtargets that require custom scheduling heuristics may +// plugin an alternate MachineSchedStrategy. The strategy is responsible for +// selecting the highest priority node from the list: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new ScheduleDAGMI(C, CustomStrategy(C)); +// } +// +// The DAG builder can also be customized in a sense by adding DAG mutations +// that will run after DAG building and before list scheduling. DAG mutations +// can adjust dependencies based on target-specific knowledge or add weak edges +// to aid heuristics: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C)); +// DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI)); +// return DAG; +// } +// +// A target that supports alternative schedulers can use the +// MachineSchedRegistry to allow command line selection. This can be done by // implementing the following boilerplate: // // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { @@ -18,9 +58,19 @@ // SchedCustomRegistry("custom", "Run my target's custom scheduler", // createCustomMachineSched); // -// Inside PassConfig: -// enablePass(&MachineSchedulerID); -// MachineSchedRegistry::setDefault(createCustomMachineSched); +// +// Finally, subtargets that don't need to implement custom heuristics but would +// like to configure the GenericScheduler's policy for a given scheduler region, +// including scheduling direction and register pressure tracking policy, can do +// this: +// +// void Subtarget:: +// overrideSchedPolicy(MachineSchedPolicy &Policy, +// MachineInstr *begin, +// MachineInstr *end, +// unsigned NumRegionInstrs) const { +// Policy. = true; +// } // //===----------------------------------------------------------------------===// @@ -30,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/Target/TargetInstrInfo.h" namespace llvm { @@ -86,15 +135,6 @@ public: static MachineSchedRegistry *getList() { return (MachineSchedRegistry *)Registry.getList(); } - static ScheduleDAGCtor getDefault() { - return (ScheduleDAGCtor)Registry.getDefault(); - } - static void setDefault(ScheduleDAGCtor C) { - Registry.setDefault((MachinePassCtor)C); - } - static void setDefault(StringRef Name) { - Registry.setDefault(Name); - } static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } @@ -102,12 +142,41 @@ public: class ScheduleDAGMI; +/// Define a generic scheduling policy for targets that don't provide their own +/// MachineSchedStrategy. This can be overriden for each scheduling region +/// before building the DAG. +struct MachineSchedPolicy { + // Allow the scheduler to disable register pressure tracking. + bool ShouldTrackPressure; + + // Allow the scheduler to force top-down or bottom-up scheduling. If neither + // is true, the scheduler runs in both directions and converges. + bool OnlyTopDown; + bool OnlyBottomUp; + + MachineSchedPolicy(): + ShouldTrackPressure(false), OnlyTopDown(false), OnlyBottomUp(false) {} +}; + /// MachineSchedStrategy - Interface to the scheduling algorithm used by /// ScheduleDAGMI. +/// +/// Initialization sequence: +/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots class MachineSchedStrategy { + virtual void anchor(); public: virtual ~MachineSchedStrategy() {} + /// Optionally override the per-region scheduling policy. + virtual void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) {} + + /// Check if pressure tracking is needed before building the DAG and + /// initializing this strategy. Called after initPolicy. + virtual bool shouldTrackPressure() const { return true; } + /// Initialize the strategy after building the DAG for a new region. virtual void initialize(ScheduleDAGMI *DAG) = 0; @@ -194,6 +263,7 @@ public: /// Mutate the DAG as a postpass after normal DAG building. class ScheduleDAGMutation { + virtual void anchor(); public: virtual ~ScheduleDAGMutation() {} @@ -222,14 +292,20 @@ protected: MachineBasicBlock::iterator LiveRegionEnd; - /// Register pressure in this region computed by buildSchedGraph. + // Map each SU to its summary of pressure changes. This array is updated for + // liveness during bottom-up scheduling. Top-down scheduling may proceed but + // has no affect on the pressure diffs. + PressureDiffs SUPressureDiffs; + + /// Register pressure in this region computed by initRegPressure. + bool ShouldTrackPressure; IntervalPressure RegPressure; RegPressureTracker RPTracker; /// List of pressure sets that exceed the target's pressure limit before /// scheduling, listed in increasing set ID order. Each pressure set is paired /// with its max pressure in the currently scheduled regions. - std::vector RegionCriticalPSets; + std::vector RegionCriticalPSets; /// The top of the unscheduled zone. MachineBasicBlock::iterator CurrentTop; @@ -255,8 +331,9 @@ public: ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), - Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(), - TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure), + Topo(SUnits, &ExitSU), ShouldTrackPressure(false), + RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), + CurrentBottom(), BotRPTracker(BotPressure), NextClusterPred(NULL), NextClusterSucc(NULL) { #ifndef NDEBUG NumInstrsScheduled = 0; @@ -265,6 +342,9 @@ public: virtual ~ScheduleDAGMI(); + /// \brief Return true if register pressure tracking is enabled. + bool isTrackingPressure() const { return ShouldTrackPressure; } + /// Add a postprocessing step to the DAG builder. /// Mutations are applied in the order that they are added after normal DAG /// building and before MachineSchedStrategy initialization. @@ -294,8 +374,7 @@ public: void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); - + unsigned regioninstrs) LLVM_OVERRIDE; /// Implement ScheduleDAGInstrs interface for scheduling a sequence of /// reorderable instructions. @@ -316,10 +395,14 @@ public: /// Get register pressure for the entire scheduling region before scheduling. const IntervalPressure &getRegPressure() const { return RegPressure; } - const std::vector &getRegionCriticalPSets() const { + const std::vector &getRegionCriticalPSets() const { return RegionCriticalPSets; } + PressureDiff &getPressureDiff(const SUnit *SU) { + return SUPressureDiffs[SU->NodeNum]; + } + const SUnit *getNextClusterPred() const { return NextClusterPred; } const SUnit *getNextClusterSucc() const { return NextClusterSucc; } @@ -333,6 +416,9 @@ public: BitVector &getScheduledTrees() { return ScheduledTrees; } + /// Compute the cyclic critical path through the DAG. + unsigned computeCyclicCriticalPath(); + void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; void viewGraph() LLVM_OVERRIDE; @@ -368,7 +454,10 @@ protected: void initRegPressure(); - void updateScheduledPressure(const std::vector &NewMaxPressure); + void updatePressureDiffs(ArrayRef LiveUses); + + void updateScheduledPressure(const SUnit *SU, + const std::vector &NewMaxPressure); bool checkSchedLimit(); diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index 85bf511d60229..aca0a91303426 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -20,79 +20,63 @@ #include "llvm/ADT/ilist_node.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 llvm::ilist NodeList; - typedef llvm::ilist EdgeList; - public: - typedef NodeEntry* NodeItr; - typedef const NodeEntry* ConstNodeItr; - - typedef EdgeEntry* EdgeItr; - typedef const EdgeEntry* ConstEdgeItr; + typedef unsigned NodeId; + typedef unsigned EdgeId; private: - typedef std::list AdjEdgeList; - + typedef std::set AdjEdgeList; + public: typedef AdjEdgeList::iterator AdjEdgeItr; private: - class NodeEntry : public llvm::ilist_node { - friend struct llvm::ilist_sentinel_traits; + class NodeEntry { private: - Vector costs; + Vector costs; AdjEdgeList adjEdges; - unsigned degree; void *data; NodeEntry() : costs(0, 0) {} public: - NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + NodeEntry(const Vector &costs) : costs(costs), data(0) {} Vector& getCosts() { return costs; } const Vector& getCosts() const { return costs; } - unsigned getDegree() const { return degree; } + unsigned getDegree() const { return adjEdges.size(); } AdjEdgeItr edgesBegin() { return adjEdges.begin(); } AdjEdgeItr edgesEnd() { return adjEdges.end(); } - AdjEdgeItr addEdge(EdgeItr e) { - ++degree; + AdjEdgeItr addEdge(EdgeId e) { 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 : public llvm::ilist_node { - friend struct llvm::ilist_sentinel_traits; + class EdgeEntry { private: - NodeItr node1, node2; + NodeId node1, node2; Matrix costs; AdjEdgeItr node1AEItr, node2AEItr; void *data; - EdgeEntry() : costs(0, 0, 0) {} + EdgeEntry() : costs(0, 0, 0), data(0) {} public: - EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs) : node1(node1), node2(node2), costs(costs) {} - NodeItr getNode1() const { return node1; } - NodeItr getNode2() const { return node2; } + NodeId getNode1() const { return node1; } + NodeId getNode2() const { return node2; } Matrix& getCosts() { return costs; } const Matrix& getCosts() const { return costs; } void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } @@ -105,254 +89,305 @@ namespace PBQP { // ----- MEMBERS ----- - NodeList nodes; - unsigned numNodes; + typedef std::vector NodeVector; + typedef std::vector FreeNodeVector; + NodeVector nodes; + FreeNodeVector freeNodes; - EdgeList edges; - unsigned numEdges; + typedef std::vector EdgeVector; + typedef std::vector FreeEdgeVector; + EdgeVector edges; + FreeEdgeVector freeEdges; // ----- 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); + NodeEntry& getNode(NodeId nId) { return nodes[nId]; } + const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; } + + EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; } + const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; } + + NodeId addConstructedNode(const NodeEntry &n) { + NodeId nodeId = 0; + if (!freeNodes.empty()) { + nodeId = freeNodes.back(); + freeNodes.pop_back(); + nodes[nodeId] = n; + } else { + nodeId = nodes.size(); + nodes.push_back(n); + } + return nodeId; } - EdgeItr addConstructedEdge(const EdgeEntry &e) { - assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + EdgeId addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() && "Attempt to add duplicate edge."); - ++numEdges; - EdgeItr edgeItr = edges.insert(edges.end(), e); - EdgeEntry &ne = getEdge(edgeItr); + EdgeId edgeId = 0; + if (!freeEdges.empty()) { + edgeId = freeEdges.back(); + freeEdges.pop_back(); + edges[edgeId] = e; + } else { + edgeId = edges.size(); + edges.push_back(e); + } + + EdgeEntry &ne = getEdge(edgeId); 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; + + ne.setNode1AEItr(n1.addEdge(edgeId)); + ne.setNode2AEItr(n2.addEdge(edgeId)); + return edgeId; } - inline void copyFrom(const Graph &other); + Graph(const Graph &other) {} + void operator=(const Graph &other) {} + public: - /// \brief Construct an empty PBQP graph. - Graph() : numNodes(0), numEdges(0) {} + class NodeItr { + public: + NodeItr(NodeId nodeId, const Graph &g) + : nodeId(nodeId), endNodeId(g.nodes.size()), freeNodes(g.freeNodes) { + this->nodeId = findNextInUse(nodeId); // Move to the first in-use nodeId + } - /// \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); - } + bool operator==(const NodeItr& n) const { return nodeId == n.nodeId; } + bool operator!=(const NodeItr& n) const { return !(*this == n); } + NodeItr& operator++() { nodeId = findNextInUse(++nodeId); return *this; } + NodeId operator*() const { return nodeId; } - /// \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; - } + private: + NodeId findNextInUse(NodeId n) const { + while (n < endNodeId && + std::find(freeNodes.begin(), freeNodes.end(), n) != + freeNodes.end()) { + ++n; + } + return n; + } + + NodeId nodeId, endNodeId; + const FreeNodeVector& freeNodes; + }; + + class EdgeItr { + public: + EdgeItr(EdgeId edgeId, const Graph &g) + : edgeId(edgeId), endEdgeId(g.edges.size()), freeEdges(g.freeEdges) { + this->edgeId = findNextInUse(edgeId); // Move to the first in-use edgeId + } + + bool operator==(const EdgeItr& n) const { return edgeId == n.edgeId; } + bool operator!=(const EdgeItr& n) const { return !(*this == n); } + EdgeItr& operator++() { edgeId = findNextInUse(++edgeId); return *this; } + EdgeId operator*() const { return edgeId; } + + private: + EdgeId findNextInUse(EdgeId n) const { + while (n < endEdgeId && + std::find(freeEdges.begin(), freeEdges.end(), n) != + freeEdges.end()) { + ++n; + } + return n; + } + + EdgeId edgeId, endEdgeId; + const FreeEdgeVector& freeEdges; + }; + + /// \brief Construct an empty PBQP graph. + Graph() {} /// \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) { + NodeId 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. + /// @param n1Id First node. + /// @param n2Id 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() && + EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) { + assert(getNodeCosts(n1Id).getLength() == costs.getRows() && + getNodeCosts(n2Id).getLength() == costs.getCols() && "Matrix dimensions mismatch."); - return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs)); } /// \brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. - unsigned getNumNodes() const { return numNodes; } + unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); } /// \brief Get the number of edges in the graph. /// @return Number of edges in the graph. - unsigned getNumEdges() const { return numEdges; } + unsigned getNumEdges() const { return edges.size() - freeEdges.size(); } /// \brief Get a node's cost vector. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); } /// \brief Get a node's cost vector (const version). - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - const Vector& getNodeCosts(ConstNodeItr nItr) const { - return getNode(nItr).getCosts(); + const Vector& getNodeCosts(NodeId nId) const { + return getNode(nId).getCosts(); } /// \brief Set a node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @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); } + void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); } /// \brief Get the node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Pointer to node data. - void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } - + void* getNodeData(NodeId nId) { return getNode(nId).getData(); } + /// \brief Get an edge's cost matrix. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); } /// \brief Get an edge's cost matrix (const version). - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { - return getEdge(eItr).getCosts(); + const Matrix& getEdgeCosts(EdgeId eId) const { + return getEdge(eId).getCosts(); } /// \brief Set an edge's data pointer. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @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); } + void setEdgeData(EdgeId eId, void *data) { getEdge(eId).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(); } + /// @param eId Edge id. + /// @return Pointer to edge data. + void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); } /// \brief Get a node's degree. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The degree of the node. - unsigned getNodeDegree(NodeItr nItr) const { - return getNode(nItr).getDegree(); + unsigned getNodeDegree(NodeId nId) const { + return getNode(nId).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(); } + NodeItr nodesBegin() const { return NodeItr(0, *this); } /// \brief End iterator for node set. - NodeItr nodesEnd() { return nodes.end(); } - - /// \brief End const iterator for node set. - ConstNodeItr nodesEnd() const { return nodes.end(); } + NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); } /// \brief Begin iterator for edge set. - EdgeItr edgesBegin() { return edges.begin(); } + EdgeItr edgesBegin() const { return EdgeItr(0, *this); } /// \brief End iterator for edge set. - EdgeItr edgesEnd() { return edges.end(); } + EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); } /// \brief Get begin iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Begin iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesBegin(NodeItr nItr) { - return getNode(nItr).edgesBegin(); + AdjEdgeItr adjEdgesBegin(NodeId nId) { + return getNode(nId).edgesBegin(); } /// \brief Get end iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return End iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesEnd(NodeItr nItr) { - return getNode(nItr).edgesEnd(); + AdjEdgeItr adjEdgesEnd(NodeId nId) { + return getNode(nId).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(); + /// @param eId Edge id. + /// @return The first node connected to the given edge. + NodeId getEdgeNode1(EdgeId eId) { + return getEdge(eId).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(); - } + /// @param eId Edge id. + /// @return The second node connected to the given edge. + NodeId getEdgeNode2(EdgeId eId) { + return getEdge(eId).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) { + /// @param eId Edge id. + /// @param nId Node id for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) { + EdgeEntry &e = getEdge(eId); + if (e.getNode1() == nId) { return e.getNode2(); } // else return e.getNode1(); } + EdgeId invalidEdgeId() const { + return std::numeric_limits::max(); + } + /// \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); + /// @param n1Id First node id. + /// @param n2Id Second node id. + /// @return An id for edge (n1Id, n2Id) if such an edge exists, + /// otherwise returns an invalid edge id. + EdgeId findEdge(NodeId n1Id, NodeId n2Id) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id); aeItr != aeEnd; ++aeItr) { - if ((getEdgeNode1(*aeItr) == n2Itr) || - (getEdgeNode2(*aeItr) == n2Itr)) { + if ((getEdgeNode1(*aeItr) == n2Id) || + (getEdgeNode2(*aeItr) == n2Id)) { return *aeItr; } } - return edges.end(); + return invalidEdgeId(); } /// \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); + /// @param nId Node id. + void removeNode(NodeId nId) { + NodeEntry &n = getNode(nId); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) { + EdgeId eId = *itr; + removeEdge(eId); } - nodes.erase(nItr); - --numNodes; + freeNodes.push_back(nId); } /// \brief Remove an edge from the graph. - /// @param eItr Edge iterator. - void removeEdge(EdgeItr eItr) { - EdgeEntry &e = getEdge(eItr); + /// @param eId Edge id. + void removeEdge(EdgeId eId) { + EdgeEntry &e = getEdge(eId); NodeEntry &n1 = getNode(e.getNode1()); NodeEntry &n2 = getNode(e.getNode2()); n1.removeEdge(e.getNode1AEItr()); n2.removeEdge(e.getNode2AEItr()); - edges.erase(eItr); - --numEdges; + freeEdges.push_back(eId); } /// \brief Remove all nodes and edges from the graph. void clear() { nodes.clear(); + freeNodes.clear(); edges.clear(); - numNodes = numEdges = 0; + freeEdges.clear(); } /// \brief Dump a graph to an output stream. @@ -362,7 +397,7 @@ namespace PBQP { for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); nodeItr != nodeEnd; ++nodeItr) { - const Vector& v = getNodeCosts(nodeItr); + const Vector& v = getNodeCosts(*nodeItr); os << "\n" << v.getLength() << "\n"; assert(v.getLength() != 0 && "Empty vector in graph."); os << v[0]; @@ -374,10 +409,10 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr)); - unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr)); + NodeId n1 = getEdgeNode1(*edgeItr); + NodeId n2 = getEdgeNode2(*edgeItr); assert(n1 != n2 && "PBQP graphs shound not have self-edges."); - const Matrix& m = getEdgeCosts(edgeItr); + const Matrix& m = getEdgeCosts(*edgeItr); os << "\n" << n1 << " " << n2 << "\n" << m.getRows() << " " << m.getCols() << "\n"; assert(m.getRows() != 0 && "No rows in matrix."); @@ -396,14 +431,14 @@ namespace PBQP { /// @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"; + << nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n"; } os << " edge [ len=" << getNumNodes() << " ]\n"; @@ -411,11 +446,11 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - os << " node" << getEdgeNode1(edgeItr) - << " -- node" << getEdgeNode2(edgeItr) + os << " node" << getEdgeNode1(*edgeItr) + << " -- node" << getEdgeNode2(*edgeItr) << " [ label=\""; - const Matrix &edgeCosts = getEdgeCosts(edgeItr); + const Matrix &edgeCosts = getEdgeCosts(*edgeItr); for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { os << edgeCosts.getRowAsVector(i) << "\\n"; @@ -427,39 +462,16 @@ namespace PBQP { }; - 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; +// 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)); - } - - } +// for (Graph::ConstNodeItr nItr = other.nodesBegin(), +// nEnd = other.nodesEnd(); +// nItr != nEnd; ++nItr) { +// nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); +// } +// } } diff --git a/include/llvm/CodeGen/PBQP/HeuristicBase.h b/include/llvm/CodeGen/PBQP/HeuristicBase.h index 0c1fcb7eaf78d..8bcbb9ed1d6b5 100644 --- a/include/llvm/CodeGen/PBQP/HeuristicBase.h +++ b/include/llvm/CodeGen/PBQP/HeuristicBase.h @@ -27,7 +27,7 @@ namespace PBQP { ///
  • 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 + ///
  • 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). @@ -39,7 +39,7 @@ namespace PBQP { /// /// 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. @@ -52,7 +52,7 @@ namespace PBQP { class HeuristicBase { private: - typedef std::list OptimalList; + typedef std::list OptimalList; HeuristicSolverImpl &s; Graph &g; @@ -62,9 +62,9 @@ namespace PBQP { 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); + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeId nId) { + optimalList.insert(optimalList.end(), nId); } public: @@ -94,7 +94,7 @@ namespace PBQP { /// behaviour. bool solverRunSimplify() const { return true; } - /// \brief Decide whether a node should be optimally or heuristically + /// \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). @@ -105,21 +105,21 @@ namespace PBQP { /// 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) + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (g.getNodeDegree(nId) < 3) return true; // else return false; } /// \brief Add the given node to the list of nodes to be optimally reduced. - /// @param nItr Node iterator to be added. + /// @param nId Node id 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); + void addToOptimalReduceList(Graph::NodeId nId) { + optimalList.push_back(nId); } /// \brief Initialise the heuristic. @@ -132,10 +132,10 @@ namespace PBQP { void setup() { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (impl().shouldOptimallyReduce(nItr)) { - addToOptimalReduceList(nItr); + if (impl().shouldOptimallyReduce(*nItr)) { + addToOptimalReduceList(*nItr); } else { - impl().addToHeuristicReduceList(nItr); + impl().addToHeuristicReduceList(*nItr); } } } @@ -150,13 +150,13 @@ namespace PBQP { if (optimalList.empty()) return false; - Graph::NodeItr nItr = optimalList.front(); + Graph::NodeId nId = 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; + switch (s.getSolverDegree(nId)) { + case 0: s.applyR0(nId); break; + case 1: s.applyR1(nId); break; + case 2: s.applyR2(nId); break; default: llvm_unreachable( "Optimal reductions of degree > 2 nodes is invalid."); } @@ -184,8 +184,8 @@ namespace PBQP { } /// \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) { + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } @@ -199,31 +199,31 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { llvm_unreachable("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) { + /// @param eId Edge id. + void postUpdateEdgeCostts(Graph::EdgeId eId) { llvm_unreachable("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) { + /// @param eId Edge id for the added edge. + void handleAddEdge(Graph::EdgeId eId) { llvm_unreachable("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. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id 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) { + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } diff --git a/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/include/llvm/CodeGen/PBQP/HeuristicSolver.h index 47e15b27e7444..e26ca02fff7ee 100644 --- a/include/llvm/CodeGen/PBQP/HeuristicSolver.h +++ b/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -9,7 +9,7 @@ // // 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. +// used to select a node for reduction. // //===----------------------------------------------------------------------===// @@ -40,10 +40,10 @@ namespace PBQP { typedef typename HImpl::NodeData HeuristicNodeData; typedef typename HImpl::EdgeData HeuristicEdgeData; - typedef std::list SolverEdges; + typedef std::list SolverEdges; public: - + /// \brief Iterator type for edges in the solver graph. typedef SolverEdges::iterator SolverEdgeItr; @@ -55,9 +55,9 @@ namespace PBQP { HeuristicNodeData& getHeuristicData() { return hData; } - SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + SolverEdgeItr addSolverEdge(Graph::EdgeId eId) { ++solverDegree; - return solverEdges.insert(solverEdges.end(), eItr); + return solverEdges.insert(solverEdges.end(), eId); } void removeSolverEdge(SolverEdgeItr seItr) { @@ -70,15 +70,15 @@ namespace PBQP { unsigned getSolverDegree() const { return solverDegree; } void clearSolverEdges() { solverDegree = 0; - solverEdges.clear(); + solverEdges.clear(); } - + private: HeuristicNodeData hData; unsigned solverDegree; SolverEdges solverEdges; }; - + class EdgeData { public: HeuristicEdgeData& getHeuristicData() { return hData; } @@ -104,7 +104,7 @@ namespace PBQP { Graph &g; HImpl h; Solution s; - std::vector stack; + std::vector stack; typedef std::list NodeDataList; NodeDataList nodeDataList; @@ -117,7 +117,7 @@ namespace PBQP { /// \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) {} + 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 @@ -125,46 +125,46 @@ namespace PBQP { Graph& getGraph() { return g; } /// \brief Get the heuristic data attached to the given node. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The heuristic data attached to the given node. - HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).getHeuristicData(); + HeuristicNodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolverNodeData(nId).getHeuristicData(); } /// \brief Get the heuristic data attached to the given edge. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return The heuristic data attached to the given node. - HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolverEdgeData(eItr).getHeuristicData(); + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolverEdgeData(eId).getHeuristicData(); } /// \brief Begin iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @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(); + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesBegin(); } /// \brief End iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @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(); + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesEnd(); } /// \brief Remove a node from the solver graph. - /// @param eItr Edge iterator for edge to be removed. + /// @param eId Edge id 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)); + void removeSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); @@ -188,66 +188,66 @@ namespace PBQP { } /// \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); + /// @param nId Node id to add to the reduction stack. + void pushToStack(Graph::NodeId nId) { + getSolverNodeData(nId).clearSolverEdges(); + stack.push_back(nId); } /// \brief Returns the solver degree of the given node. - /// @param nItr Node iterator for which degree is requested. + /// @param nId Node id 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(); + unsigned getSolverDegree(Graph::NodeId nId) { + return getSolverNodeData(nId).getSolverDegree(); } /// \brief Set the solution of the given node. - /// @param nItr Node iterator to set solution for. + /// @param nId Node id to set solution for. /// @param selection Selection for node. - void setSolution(const Graph::NodeItr &nItr, unsigned selection) { - s.setSelection(nItr, selection); + void setSolution(const Graph::NodeId &nId, unsigned selection) { + s.setSelection(nId, selection); - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr(*aeItr); - Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); - getSolverNodeData(anItr).addSolverEdge(eItr); + Graph::EdgeId eId(*aeItr); + Graph::NodeId anId(g.getEdgeOtherNode(eId, nId)); + getSolverNodeData(anId).addSolverEdge(eId); } } /// \brief Apply rule R0. - /// @param nItr Node iterator for node to apply R0 to. + /// @param nId Node id 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 && + void applyR0(Graph::NodeId nId) { + assert(getSolverNodeData(nId).getSolverDegree() == 0 && "R0 applied to node with degree != 0."); // Nothing to do. Just push the node onto the reduction stack. - pushToStack(nItr); + pushToStack(nId); s.recordR0(); } /// \brief Apply rule R1. - /// @param xnItr Node iterator for node to apply R1 to. + /// @param xnId Node id for node to apply R1 to. /// /// Node will be automatically pushed to the solver stack. - void applyR1(Graph::NodeItr xnItr) { - NodeData &nd = getSolverNodeData(xnItr); + void applyR1(Graph::NodeId xnId) { + NodeData &nd = getSolverNodeData(xnId); assert(nd.getSolverDegree() == 1 && "R1 applied to node with degree != 1."); - Graph::EdgeItr eItr = *nd.solverEdgesBegin(); + Graph::EdgeId eId = *nd.solverEdgesBegin(); + + const Matrix &eCosts = g.getEdgeCosts(eId); + const Vector &xCosts = g.getNodeCosts(xnId); - 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); + if (xnId == g.getEdgeNode1(eId)) { + Graph::NodeId ynId = g.getEdgeNode2(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned j = 0; j < yCosts.getLength(); ++j) { PBQPNum min = eCosts[0][j] + xCosts[0]; for (unsigned i = 1; i < xCosts.getLength(); ++i) { @@ -257,10 +257,10 @@ namespace PBQP { } yCosts[j] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } else { - Graph::NodeItr ynItr = g.getEdgeNode1(eItr); - Vector &yCosts = g.getNodeCosts(ynItr); + Graph::NodeId ynId = g.getEdgeNode1(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned i = 0; i < yCosts.getLength(); ++i) { PBQPNum min = eCosts[i][0] + xCosts[0]; for (unsigned j = 1; j < xCosts.getLength(); ++j) { @@ -270,48 +270,48 @@ namespace PBQP { } yCosts[i] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } - removeSolverEdge(eItr); + removeSolverEdge(eId); assert(nd.getSolverDegree() == 0 && "Degree 1 with edge removed should be 0."); - pushToStack(xnItr); + pushToStack(xnId); s.recordR1(); } /// \brief Apply rule R2. - /// @param xnItr Node iterator for node to apply R2 to. + /// @param xnId Node id 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 && + void applyR2(Graph::NodeId xnId) { + assert(getSolverNodeData(xnId).getSolverDegree() == 2 && "R2 applied to node with degree != 2."); - NodeData &nd = getSolverNodeData(xnItr); - const Vector &xCosts = g.getNodeCosts(xnItr); + NodeData &nd = getSolverNodeData(xnId); + const Vector &xCosts = g.getNodeCosts(xnId); SolverEdgeItr aeItr = nd.solverEdgesBegin(); - Graph::EdgeItr yxeItr = *aeItr, - zxeItr = *(++aeItr); + Graph::EdgeId yxeId = *aeItr, + zxeId = *(++aeItr); - Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), - znItr = g.getEdgeOtherNode(zxeItr, xnItr); + Graph::NodeId ynId = g.getEdgeOtherNode(yxeId, xnId), + znId = g.getEdgeOtherNode(zxeId, xnId); - bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), - flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); + bool flipEdge1 = (g.getEdgeNode1(yxeId) == xnId), + flipEdge2 = (g.getEdgeNode1(zxeId) == xnId); const Matrix *yxeCosts = flipEdge1 ? - new Matrix(g.getEdgeCosts(yxeItr).transpose()) : - &g.getEdgeCosts(yxeItr); + new Matrix(g.getEdgeCosts(yxeId).transpose()) : + &g.getEdgeCosts(yxeId); const Matrix *zxeCosts = flipEdge2 ? - new Matrix(g.getEdgeCosts(zxeItr).transpose()) : - &g.getEdgeCosts(zxeItr); + new Matrix(g.getEdgeCosts(zxeId).transpose()) : + &g.getEdgeCosts(zxeId); unsigned xLen = xCosts.getLength(), yLen = yxeCosts->getRows(), zLen = zxeCosts->getRows(); - + Matrix delta(yLen, zLen); for (unsigned i = 0; i < yLen; ++i) { @@ -333,79 +333,79 @@ namespace PBQP { if (flipEdge2) delete zxeCosts; - Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + Graph::EdgeId yzeId = g.findEdge(ynId, znId); bool addedEdge = false; - if (yzeItr == g.edgesEnd()) { - yzeItr = g.addEdge(ynItr, znItr, delta); + if (yzeId == g.invalidEdgeId()) { + yzeId = g.addEdge(ynId, znId, delta); addedEdge = true; } else { - Matrix &yzeCosts = g.getEdgeCosts(yzeItr); - h.preUpdateEdgeCosts(yzeItr); - if (ynItr == g.getEdgeNode1(yzeItr)) { + Matrix &yzeCosts = g.getEdgeCosts(yzeId); + h.preUpdateEdgeCosts(yzeId); + if (ynId == g.getEdgeNode1(yzeId)) { yzeCosts += delta; } else { yzeCosts += delta.transpose(); } } - bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeId); if (!addedEdge) { // If we modified the edge costs let the heuristic know. - h.postUpdateEdgeCosts(yzeItr); + h.postUpdateEdgeCosts(yzeId); } - + 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); + h.handleRemoveEdge(yzeId, ynId); + h.handleRemoveEdge(yzeId, znId); + removeSolverEdge(yzeId); } - g.removeEdge(yzeItr); + g.removeEdge(yzeId); } 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); + g.setEdgeData(yzeId, &edgeDataList.back()); + addSolverEdge(yzeId); + h.handleAddEdge(yzeId); } - h.handleRemoveEdge(yxeItr, ynItr); - removeSolverEdge(yxeItr); - h.handleRemoveEdge(zxeItr, znItr); - removeSolverEdge(zxeItr); + h.handleRemoveEdge(yxeId, ynId); + removeSolverEdge(yxeId); + h.handleRemoveEdge(zxeId, znId); + removeSolverEdge(zxeId); - pushToStack(xnItr); + pushToStack(xnId); s.recordR2(); } /// \brief Record an application of the RN rule. /// /// For use by the HeuristicBase. - void recordRN() { s.recordRN(); } + void recordRN() { s.recordRN(); } private: - NodeData& getSolverNodeData(Graph::NodeItr nItr) { - return *static_cast(g.getNodeData(nItr)); + NodeData& getSolverNodeData(Graph::NodeId nId) { + return *static_cast(g.getNodeData(nId)); } - EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { - return *static_cast(g.getEdgeData(eItr)); + EdgeData& getSolverEdgeData(Graph::EdgeId eId) { + return *static_cast(g.getEdgeData(eId)); } - void addSolverEdge(Graph::EdgeItr eItr) { - EdgeData &eData = getSolverEdgeData(eItr); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + void addSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); - eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); - eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eId)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eId)); } void setup() { @@ -417,15 +417,15 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { nodeDataList.push_back(NodeData()); - g.setNodeData(nItr, &nodeDataList.back()); + 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); + g.setEdgeData(*eItr, &edgeDataList.back()); + addSolverEdge(*eItr); } } @@ -441,28 +441,30 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (g.getNodeCosts(nItr).getLength() == 1) { + Graph::NodeId nId = *nItr; + + if (g.getNodeCosts(nId).getLength() == 1) { - std::vector edgesToRemove; + std::vector edgesToRemove; - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr = *aeItr; + Graph::EdgeId eId = *aeItr; - if (g.getEdgeNode1(eItr) == nItr) { - Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getRowAsVector(0); + if (g.getEdgeNode1(eId) == nId) { + Graph::NodeId otherNodeId = g.getEdgeNode2(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getRowAsVector(0); } else { - Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getColAsVector(0); + Graph::NodeId otherNodeId = g.getEdgeNode1(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getColAsVector(0); } - edgesToRemove.push_back(eItr); + edgesToRemove.push_back(eId); } if (!edgesToRemove.empty()) @@ -477,12 +479,12 @@ namespace PBQP { } void eliminateIndependentEdges() { - std::vector edgesToProcess; + std::vector edgesToProcess; unsigned numEliminated = 0; for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); eItr != eEnd; ++eItr) { - edgesToProcess.push_back(eItr); + edgesToProcess.push_back(*eItr); } while (!edgesToProcess.empty()) { @@ -492,21 +494,21 @@ namespace PBQP { } } - bool tryToEliminateEdge(Graph::EdgeItr eItr) { - if (tryNormaliseEdgeMatrix(eItr)) { - g.removeEdge(eItr); - return true; + bool tryToEliminateEdge(Graph::EdgeId eId) { + if (tryNormaliseEdgeMatrix(eId)) { + g.removeEdge(eId); + return true; } return false; } - bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + bool tryNormaliseEdgeMatrix(Graph::EdgeId &eId) { 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)); + Matrix &edgeCosts = g.getEdgeCosts(eId); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eId)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eId)); for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { PBQPNum rowMin = infinity; @@ -554,34 +556,34 @@ namespace PBQP { } } - void computeSolution(Graph::NodeItr nItr) { + void computeSolution(Graph::NodeId nId) { - NodeData &nodeData = getSolverNodeData(nItr); + NodeData &nodeData = getSolverNodeData(nId); - Vector v(g.getNodeCosts(nItr)); + Vector v(g.getNodeCosts(nId)); // 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); + Graph::EdgeId eId(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eId); - if (nItr == g.getEdgeNode1(eItr)) { - Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + if (nId == g.getEdgeNode1(eId)) { + Graph::NodeId adjNode(g.getEdgeNode2(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getColAsVector(adjSolution); } else { - Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + Graph::NodeId adjNode(g.getEdgeNode1(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getRowAsVector(adjSolution); } } - setSolution(nItr, v.minIndex()); + setSolution(nId, v.minIndex()); } void cleanup() { diff --git a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h index 307d81e1d161c..c355c2c2f81a0 100644 --- a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -27,7 +27,7 @@ namespace PBQP { /// \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 @@ -39,16 +39,16 @@ namespace PBQP { /// 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. + /// + /// 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)) + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + if (s->getSolverDegree(n1Id) > s->getSolverDegree(n2Id)) return true; return false; } @@ -60,12 +60,12 @@ namespace PBQP { 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); + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + const PBQP::Vector &cv1 = g->getNodeCosts(n1Id); + const PBQP::Vector &cv2 = g->getNodeCosts(n2Id); - PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr); - PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr); + PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Id); + PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Id); if (cost1 < cost2) return true; @@ -77,10 +77,10 @@ namespace PBQP { Graph *g; }; - typedef std::list RNAllocableList; + typedef std::list RNAllocableList; typedef RNAllocableList::iterator RNAllocableListItr; - typedef std::list RNUnallocableList; + typedef std::list RNUnallocableList; typedef RNUnallocableList::iterator RNUnallocableListItr; public: @@ -114,7 +114,7 @@ namespace PBQP { /// \brief Determine whether a node should be reduced using optimal /// reduction. - /// @param nItr Node iterator to be considered. + /// @param nId Node id to be considered. /// @return True if the given node should be optimally reduced, false /// otherwise. /// @@ -123,8 +123,8 @@ namespace PBQP { /// 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) { + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (getSolver().getSolverDegree(nId) < 3) { return true; } // else @@ -132,15 +132,15 @@ namespace PBQP { } /// \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); + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + initializeNode(nId); nd.isHeuristic = true; if (nd.isAllocable) { - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } else { - nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nId); } } @@ -159,19 +159,19 @@ namespace PBQP { RNAllocableListItr rnaItr = min_element(rnAllocableList.begin(), rnAllocableList.end(), LinkDegreeComparator(getSolver())); - Graph::NodeItr nItr = *rnaItr; + Graph::NodeId nId = *rnaItr; rnAllocableList.erase(rnaItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } else if (!rnUnallocableList.empty()) { RNUnallocableListItr rnuItr = min_element(rnUnallocableList.begin(), rnUnallocableList.end(), SpillCostComparator(getSolver())); - Graph::NodeItr nItr = *rnuItr; + Graph::NodeId nId = *rnuItr; rnUnallocableList.erase(rnuItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } // else @@ -179,43 +179,43 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); if (n1.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode1(eId)); if (n2.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode2(eId)); - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); ed.isUpToDate = false; } /// \brief Handle the change in the costs on the given edge. - /// @param eItr Edge iterator. - void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void postUpdateEdgeCosts(Graph::EdgeId eId) { // This is effectively the same as adding a new edge now, since // we've factored out the costs of the old one. - handleAddEdge(eItr); + handleAddEdge(eId); } /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eItr Edge iterator for the added edge. + /// @param eId Edge id 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) { + void handleAddEdge(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); // If neither node is managed by the heuristic there's nothing to be // done. @@ -223,60 +223,60 @@ namespace PBQP { return; // Ok - we need to update at least one node. - computeEdgeContributions(eItr); + computeEdgeContributions(eId); // Update node 1 if it's managed by the heuristic. if (n1.isHeuristic) { bool n1WasAllocable = n1.isAllocable; - addEdgeContributions(eItr, n1Itr); - updateAllocability(n1Itr); + addEdgeContributions(eId, n1Id); + updateAllocability(n1Id); if (n1WasAllocable && !n1.isAllocable) { rnAllocableList.erase(n1.rnaItr); n1.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n1Id); } } // Likewise for node 2. if (n2.isHeuristic) { bool n2WasAllocable = n2.isAllocable; - addEdgeContributions(eItr, n2Itr); - updateAllocability(n2Itr); + addEdgeContributions(eId, n2Id); + updateAllocability(n2Id); if (n2WasAllocable && !n2.isAllocable) { rnAllocableList.erase(n2.rnaItr); n2.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n2Id); } } } /// \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. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id 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); + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { + NodeData &nd =getHeuristicNodeData(nId); // If the node is not managed by the heuristic there's nothing to be // done. if (!nd.isHeuristic) return; - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); (void)ed; assert(ed.isUpToDate && "Edge data is not up to date."); // Update node. bool ndWasAllocable = nd.isAllocable; - subtractEdgeContributions(eItr, nItr); - updateAllocability(nItr); + subtractEdgeContributions(eId, nId); + updateAllocability(nId); // If the node has gone optimal... - if (shouldOptimallyReduce(nItr)) { + if (shouldOptimallyReduce(nId)) { nd.isHeuristic = false; - addToOptimalReduceList(nItr); + addToOptimalReduceList(nId); if (ndWasAllocable) { rnAllocableList.erase(nd.rnaItr); } else { @@ -287,36 +287,36 @@ namespace PBQP { // from "unallocable" to "allocable". if (!ndWasAllocable && nd.isAllocable) { rnUnallocableList.erase(nd.rnuItr); - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } } } private: - NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolver().getHeuristicNodeData(nItr); + NodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolver().getHeuristicNodeData(nId); } - EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolver().getHeuristicEdgeData(eItr); + EdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolver().getHeuristicEdgeData(eId); } // 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); + void computeEdgeContributions(Graph::EdgeId eId) { + EdgeData &ed = getHeuristicEdgeData(eId); if (ed.isUpToDate) return; // Edge data is already up to date. - Matrix &eCosts = getGraph().getEdgeCosts(eItr); + Matrix &eCosts = getGraph().getEdgeCosts(eId); unsigned numRegs = eCosts.getRows() - 1, numReverseRegs = eCosts.getCols() - 1; std::vector rowInfCounts(numRegs, 0), - colInfCounts(numReverseRegs, 0); + colInfCounts(numReverseRegs, 0); ed.worst = 0; ed.reverseWorst = 0; @@ -348,19 +348,19 @@ namespace PBQP { ed.isUpToDate = true; } - // Add the contributions of the given edge to the given node's + // 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); + void addEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); 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); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); EdgeData::UnsafeArray &unsafe = nIsNode1 ? ed.unsafe : ed.reverseUnsafe; nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; @@ -375,25 +375,25 @@ namespace PBQP { } } - // Subtract the contributions of the given edge to the given node's + // 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); + void subtractEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); 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); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); 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 (unsafe[r]) { if (nd.unsafeDegrees[r] == 1) { ++nd.numSafe; } @@ -402,22 +402,22 @@ namespace PBQP { } } - void updateAllocability(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + void updateAllocability(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; } - void initializeNode(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); + void initializeNode(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); if (nd.isInitialized) return; // Node data is already up to date. - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.numDenied = 0; - const Vector& nCosts = getGraph().getNodeCosts(nItr); + const Vector& nCosts = getGraph().getNodeCosts(nId); for (unsigned i = 1; i < nCosts.getLength(); ++i) { if (nCosts[i] == std::numeric_limits::infinity()) ++nd.numDenied; @@ -428,27 +428,27 @@ namespace PBQP { typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), - aeEnd = getSolver().solverEdgesEnd(nItr); + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nId), + aeEnd = getSolver().solverEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - - Graph::EdgeItr eItr = *aeItr; - computeEdgeContributions(eItr); - addEdgeContributions(eItr, nItr); + + Graph::EdgeId eId = *aeItr; + computeEdgeContributions(eId); + addEdgeContributions(eId, nId); } - updateAllocability(nItr); + updateAllocability(nId); nd.isInitialized = true; } - void handleRemoveNode(Graph::NodeItr xnItr) { + void handleRemoveNode(Graph::NodeId xnId) { typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; - std::vector edgesToRemove; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), - aeEnd = getSolver().solverEdgesEnd(xnItr); + std::vector edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnId), + aeEnd = getSolver().solverEdgesEnd(xnId); aeItr != aeEnd; ++aeItr) { - Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); - handleRemoveEdge(*aeItr, ynItr); + Graph::NodeId ynId = getGraph().getEdgeOtherNode(*aeItr, xnId); + handleRemoveEdge(*aeItr, ynId); edgesToRemove.push_back(*aeItr); } while (!edgesToRemove.empty()) { diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index b9f288bbeeb48..091805d00f3e2 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -26,8 +26,7 @@ namespace PBQP { class Solution { private: - typedef std::map SelectionsMap; + typedef std::map SelectionsMap; SelectionsMap selections; unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; @@ -71,17 +70,17 @@ namespace PBQP { 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; + /// @param nodeId Node id. + /// @param selection Selection for nodeId. + void setSelection(Graph::NodeId nodeId, unsigned selection) { + selections[nodeId] = 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); + /// @param nodeId Node id. + /// @return The selection for nodeId; + unsigned getSelection(Graph::NodeId nodeId) const { + SelectionsMap::const_iterator sItr = selections.find(nodeId); assert(sItr != selections.end() && "No selection for node."); return sItr->second; } diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index b02f63e70b9fc..ae4a2fa0bf83e 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -21,19 +21,22 @@ namespace llvm { - class FunctionPass; - class MachineFunctionPass; - class PassInfo; - class PassManagerBase; - class TargetLoweringBase; - class TargetLowering; - class TargetRegisterClass; - class raw_ostream; -} - -namespace llvm { - +class FunctionPass; +class MachineFunctionPass; class PassConfigImpl; +class PassInfo; +class ScheduleDAGInstrs; +class TargetLowering; +class TargetLoweringBase; +class TargetRegisterClass; +class raw_ostream; +struct MachineSchedContext; + +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +} +using legacy::PassManagerBase; /// Discriminated union of Pass ID types. /// @@ -204,6 +207,20 @@ public: /// Fully developed targets will not generally override this. virtual void addMachinePasses(); + /// createTargetScheduler - Create an instance of ScheduleDAGInstrs to be run + /// within the standard MachineScheduler pass for this function and target at + /// the current optimization level. + /// + /// This can also be used to plug a new MachineSchedStrategy into an instance + /// of the standard ScheduleDAGMI: + /// return new ScheduleDAGMI(C, new MyStrategy(C)) + /// + /// Return NULL to select the default (generic) machine scheduler. + virtual ScheduleDAGInstrs * + createMachineScheduler(MachineSchedContext *C) const { + return 0; + } + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -308,7 +325,8 @@ protected: AnalysisID addPass(AnalysisID PassID); /// Add a pass to the PassManager if that pass is supposed to be run, as - /// determined by the StartAfter and StopAfter options. + /// determined by the StartAfter and StopAfter options. Takes ownership of the + /// pass. void addPass(Pass *P); /// addMachinePasses helper to create the target-selected or overriden @@ -329,7 +347,7 @@ namespace llvm { /// This pass implements the target transform info analysis using the target /// independent information available to the LLVM code generator. ImmutablePass * - createBasicTargetTransformInfoPass(const TargetLoweringBase *TLI); + createBasicTargetTransformInfoPass(const TargetMachine *TM); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -364,14 +382,6 @@ namespace llvm { /// these register allocator like this: AU.addRequiredID(PHIEliminationID); extern char &PHIEliminationID; - /// StrongPHIElimination - 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; - /// LiveIntervals - This analysis keeps track of the live ranges of virtual /// and physical registers. extern char &LiveIntervalsID; @@ -518,7 +528,7 @@ namespace llvm { /// createStackProtectorPass - This pass adds stack protectors to functions. /// - FunctionPass *createStackProtectorPass(const TargetLoweringBase *tli); + FunctionPass *createStackProtectorPass(const TargetMachine *TM); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. @@ -527,12 +537,12 @@ namespace llvm { /// 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); + FunctionPass *createDwarfEHPass(const TargetMachine *TM); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetLoweringBase *tli); + FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index df74d08888bb7..705086c22b459 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -44,7 +44,7 @@ namespace llvm { virtual bool isAliased(const MachineFrameInfo *) const; /// mayAlias - Return true if the memory pointed to by this - /// PseudoSourceValue can ever alias a LLVM IR Value. + /// PseudoSourceValue can ever alias an LLVM IR Value. virtual bool mayAlias(const MachineFrameInfo *) const; /// classof - Methods for support type inquiry through isa, cast, and diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 8b8e3d90f73e8..7472e5a62d6b5 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -26,8 +26,8 @@ namespace llvm { class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineFunction; - class MachineLoopInfo; class TargetRegisterInfo; template class OwningPtr; @@ -52,22 +52,22 @@ namespace llvm { /// 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, + void recordVReg(unsigned vreg, PBQP::Graph::NodeId nodeId, AllowedRegsItr arBegin, AllowedRegsItr arEnd) { - assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node."); + assert(node2VReg.find(nodeId) == 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; + node2VReg[nodeId] = vreg; + vreg2Node[vreg] = nodeId; 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; + unsigned getVRegForNode(PBQP::Graph::NodeId nodeId) const; /// Get the PBQP node corresponding to the given virtual register. - PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const; + PBQP::Graph::NodeId getNodeForVReg(unsigned vreg) const; /// Returns true if the given PBQP option represents a physical register, /// false otherwise. @@ -92,9 +92,8 @@ namespace llvm { private: - typedef std::map Node2VReg; - typedef DenseMap VReg2Node; + typedef std::map Node2VReg; + typedef DenseMap VReg2Node; typedef DenseMap AllowedSetMap; PBQP::Graph graph; @@ -125,7 +124,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: @@ -144,7 +143,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 3ad22e65c8c7d..9ec12bdea0ad3 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -62,6 +62,8 @@ class RegisterClassInfo { // Reserved registers in the current MF. BitVector Reserved; + OwningArrayPtr PSetLimits; + // Compute all information about RC. void compute(const TargetRegisterClass *RC) const; @@ -126,8 +128,19 @@ public: unsigned getLastCostChange(const TargetRegisterClass *RC) { return get(RC).LastCostChange; } + + /// Get the register unit limit for the given pressure set index. + /// + /// RegisterClassInfo adjusts this limit for reserved registers. + unsigned getRegPressureSetLimit(unsigned Idx) const { + if (!PSetLimits[Idx]) + PSetLimits[Idx] = computePSetLimit(Idx); + return PSetLimits[Idx]; + } + +protected: + unsigned computePSetLimit(unsigned Idx) const; }; } // end namespace llvm #endif - diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 267018074677d..a801d1d1eee9b 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -22,7 +22,7 @@ namespace llvm { class LiveIntervals; -class LiveInterval; +class LiveRange; class RegisterClassInfo; class MachineInstr; @@ -89,16 +89,89 @@ struct RegionPressure : RegisterPressure { void openBottom(MachineBasicBlock::const_iterator PrevBottom); }; -/// An element of pressure difference that identifies the pressure set and -/// amount of increase or decrease in units of pressure. -struct PressureElement { - unsigned PSetID; - int UnitIncrease; +/// Capture a change in pressure for a single pressure set. UnitInc may be +/// expressed in terms of upward or downward pressure depending on the client +/// and will be dynamically adjusted for current liveness. +/// +/// Pressure increments are tiny, typically 1-2 units, and this is only for +/// heuristics, so we don't check UnitInc overflow. Instead, we may have a +/// higher level assert that pressure is consistent within a region. We also +/// effectively ignore dead defs which don't affect heuristics much. +class PressureChange { + uint16_t PSetID; // ID+1. 0=Invalid. + int16_t UnitInc; +public: + PressureChange(): PSetID(0), UnitInc(0) {} + PressureChange(unsigned id): PSetID(id+1), UnitInc(0) { + assert(id < UINT16_MAX && "PSetID overflow."); + } + + bool isValid() const { return PSetID > 0; } + + unsigned getPSet() const { + assert(isValid() && "invalid PressureChange"); + return PSetID - 1; + } + // If PSetID is invalid, return UINT16_MAX to give it lowest priority. + unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; } + + int getUnitInc() const { return UnitInc; } + + void setUnitInc(int Inc) { UnitInc = Inc; } + + bool operator==(const PressureChange &RHS) const { + return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; + } +}; + +template <> struct isPodLike { + static const bool value = true; +}; + +/// List of PressureChanges in order of increasing, unique PSetID. +/// +/// Use a small fixed number, because we can fit more PressureChanges in an +/// empty SmallVector than ever need to be tracked per register class. If more +/// PSets are affected, then we only track the most constrained. +class PressureDiff { + // The initial design was for MaxPSets=4, but that requires PSet partitions, + // which are not yet implemented. (PSet partitions are equivalent PSets given + // the register classes actually in use within the scheduling region.) + enum { MaxPSets = 16 }; + + PressureChange PressureChanges[MaxPSets]; +public: + typedef PressureChange* iterator; + typedef const PressureChange* const_iterator; + iterator begin() { return &PressureChanges[0]; } + iterator end() { return &PressureChanges[MaxPSets]; } + const_iterator begin() const { return &PressureChanges[0]; } + const_iterator end() const { return &PressureChanges[MaxPSets]; } + + void addPressureChange(unsigned RegUnit, bool IsDec, + const MachineRegisterInfo *MRI); +}; + +/// Array of PressureDiffs. +class PressureDiffs { + PressureDiff *PDiffArray; + unsigned Size; + unsigned Max; +public: + PressureDiffs(): PDiffArray(0), Size(0), Max(0) {} + ~PressureDiffs() { free(PDiffArray); } - PressureElement(): PSetID(~0U), UnitIncrease(0) {} - PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} + void clear() { Size = 0; } - bool isValid() const { return PSetID != ~0U; } + void init(unsigned N); + + PressureDiff &operator[](unsigned Idx) { + assert(Idx < Size && "PressureDiff index out of bounds"); + return PDiffArray[Idx]; + } + const PressureDiff &operator[](unsigned Idx) const { + return const_cast(this)->operator[](Idx); + } }; /// Store the effects of a change in pressure on things that MI scheduler cares @@ -116,11 +189,19 @@ struct PressureElement { /// CurrentMax records the largest increase in the tracker's max pressure that /// exceeds the current limit for some pressure set determined by the client. struct RegPressureDelta { - PressureElement Excess; - PressureElement CriticalMax; - PressureElement CurrentMax; + PressureChange Excess; + PressureChange CriticalMax; + PressureChange CurrentMax; RegPressureDelta() {} + + bool operator==(const RegPressureDelta &RHS) const { + return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax + && CurrentMax == RHS.CurrentMax; + } + bool operator!=(const RegPressureDelta &RHS) const { + return !operator==(RHS); + } }; /// \brief A set of live virtual registers and physical register units. @@ -131,7 +212,7 @@ struct LiveRegSet { SparseSet PhysRegs; SparseSet VirtRegs; - bool contains(unsigned Reg) { + bool contains(unsigned Reg) const { if (TargetRegisterInfo::isVirtualRegister(Reg)) return VirtRegs.count(Reg); return PhysRegs.count(Reg); @@ -183,6 +264,9 @@ class RegPressureTracker { /// or RegisterPressure. If requireIntervals is false, LIS are ignored. bool RequireIntervals; + /// True if UntiedDefs will be populated. + bool TrackUntiedDefs; + /// Register pressure corresponds to liveness before this instruction /// iterator. It may point to the end of the block or a DebugValue rather than /// an instruction. @@ -194,16 +278,26 @@ class RegPressureTracker { /// Set of live registers. LiveRegSet LiveRegs; + /// Set of vreg defs that start a live range. + SparseSet UntiedDefs; + /// Live-through pressure. + std::vector LiveThruPressure; + public: RegPressureTracker(IntervalPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true), + TrackUntiedDefs(false) {} RegPressureTracker(RegionPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false), + TrackUntiedDefs(false) {} + + void reset(); void init(const MachineFunction *mf, const RegisterClassInfo *rci, const LiveIntervals *lis, const MachineBasicBlock *mbb, - MachineBasicBlock::const_iterator pos); + MachineBasicBlock::const_iterator pos, + bool ShouldTrackUntiedDefs = false); /// Force liveness of virtual registers or physical register /// units. Particularly useful to initialize the livein/out state of the @@ -224,7 +318,7 @@ public: SlotIndex getCurrSlot() const; /// Recede across the previous instruction. - bool recede(); + bool recede(SmallVectorImpl *LiveUses = 0, PressureDiff *PDiff = 0); /// Advance across the current instruction. bool advance(); @@ -232,6 +326,17 @@ public: /// Finalize the region boundaries and recored live ins and live outs. void closeRegion(); + /// Initialize the LiveThru pressure set based on the untied defs found in + /// RPTracker. + void initLiveThru(const RegPressureTracker &RPTracker); + + /// Copy an existing live thru pressure result. + void initLiveThru(ArrayRef PressureSet) { + LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); + } + + ArrayRef getLiveThru() const { return LiveThruPressure; } + /// Get the resulting register pressure over the traversed region. /// This result is complete if either advance() or recede() has returned true, /// or if closeRegion() was explicitly invoked. @@ -256,31 +361,39 @@ public: /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxUpwardPressureDelta(const MachineInstr *MI, + PressureDiff *PDiff, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit); + void getUpwardPressureDelta(const MachineInstr *MI, + /*const*/ PressureDiff &PDiff, + RegPressureDelta &Delta, + ArrayRef CriticalPSets, + ArrayRef MaxPressureLimit) const; + /// Consider the pressure increase caused by traversing this instruction /// top-down. Find the pressure set with the most change beyond its pressure /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit); /// Find the pressure set with the most change beyond its pressure limit after /// traversing this instruction either upward or downward depending on the /// closed end of the current region. - void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + void getMaxPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit) { if (isTopClosed()) return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, MaxPressureLimit); assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets, + return getMaxUpwardPressureDelta(MI, 0, Delta, CriticalPSets, MaxPressureLimit); } @@ -304,10 +417,14 @@ public: return getDownwardPressure(MI, PressureResult, MaxPressureResult); } + bool hasUntiedDef(unsigned VirtReg) const { + return UntiedDefs.count(VirtReg); + } + void dump() const; protected: - const LiveInterval *getInterval(unsigned Reg) const; + const LiveRange *getLiveRange(unsigned Reg) const; void increaseRegPressure(ArrayRef Regs); void decreaseRegPressure(ArrayRef Regs); @@ -315,6 +432,11 @@ protected: void bumpUpwardPressure(const MachineInstr *MI); void bumpDownwardPressure(const MachineInstr *MI); }; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void dumpRegSetPressure(ArrayRef SetPressure, + const TargetRegisterInfo *TRI); +#endif } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 95bf29167c201..28ebe5361b4a9 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -131,7 +131,7 @@ public: /// Query whether a frame index is a scavenging frame index. bool isScavengingFrameIndex(int FI) const { - for (SmallVector::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex == FI) return true; @@ -141,7 +141,7 @@ public: /// Get an array of scavenging frame indices. void getScavengingFrameIndices(SmallVectorImpl &A) const { - for (SmallVector::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex >= 0) A.push_back(I->FrameIndex); diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 41289a42c4387..009b8a0f697a1 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -1,4 +1,4 @@ -//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- C++ -*-===// +//===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -188,6 +188,11 @@ namespace RTLIB { NEARBYINT_F80, NEARBYINT_F128, NEARBYINT_PPCF128, + ROUND_F32, + ROUND_F64, + ROUND_F80, + ROUND_F128, + ROUND_PPCF128, FLOOR_F32, FLOOR_F64, FLOOR_F80, @@ -320,34 +325,65 @@ namespace RTLIB { SYNC_VAL_COMPARE_AND_SWAP_2, SYNC_VAL_COMPARE_AND_SWAP_4, SYNC_VAL_COMPARE_AND_SWAP_8, + SYNC_VAL_COMPARE_AND_SWAP_16, 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_LOCK_TEST_AND_SET_16, SYNC_FETCH_AND_ADD_1, SYNC_FETCH_AND_ADD_2, SYNC_FETCH_AND_ADD_4, SYNC_FETCH_AND_ADD_8, + SYNC_FETCH_AND_ADD_16, SYNC_FETCH_AND_SUB_1, SYNC_FETCH_AND_SUB_2, SYNC_FETCH_AND_SUB_4, SYNC_FETCH_AND_SUB_8, + SYNC_FETCH_AND_SUB_16, SYNC_FETCH_AND_AND_1, SYNC_FETCH_AND_AND_2, SYNC_FETCH_AND_AND_4, SYNC_FETCH_AND_AND_8, + SYNC_FETCH_AND_AND_16, SYNC_FETCH_AND_OR_1, SYNC_FETCH_AND_OR_2, SYNC_FETCH_AND_OR_4, SYNC_FETCH_AND_OR_8, + SYNC_FETCH_AND_OR_16, SYNC_FETCH_AND_XOR_1, SYNC_FETCH_AND_XOR_2, SYNC_FETCH_AND_XOR_4, SYNC_FETCH_AND_XOR_8, + SYNC_FETCH_AND_XOR_16, SYNC_FETCH_AND_NAND_1, SYNC_FETCH_AND_NAND_2, SYNC_FETCH_AND_NAND_4, SYNC_FETCH_AND_NAND_8, + SYNC_FETCH_AND_NAND_16, + SYNC_FETCH_AND_MAX_1, + SYNC_FETCH_AND_MAX_2, + SYNC_FETCH_AND_MAX_4, + SYNC_FETCH_AND_MAX_8, + SYNC_FETCH_AND_MAX_16, + SYNC_FETCH_AND_UMAX_1, + SYNC_FETCH_AND_UMAX_2, + SYNC_FETCH_AND_UMAX_4, + SYNC_FETCH_AND_UMAX_8, + SYNC_FETCH_AND_UMAX_16, + SYNC_FETCH_AND_MIN_1, + SYNC_FETCH_AND_MIN_2, + SYNC_FETCH_AND_MIN_4, + SYNC_FETCH_AND_MIN_8, + SYNC_FETCH_AND_MIN_16, + SYNC_FETCH_AND_UMIN_1, + SYNC_FETCH_AND_UMIN_2, + SYNC_FETCH_AND_UMIN_4, + SYNC_FETCH_AND_UMIN_8, + SYNC_FETCH_AND_UMIN_16, + + // Stack Protector Fail. + STACKPROTECTOR_CHECK_FAIL, UNKNOWN_LIBCALL }; diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 7cff27e17240b..ccba1b0364e44 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -90,11 +90,6 @@ namespace llvm { /// the value of the Latency field of the predecessor, however advanced /// models may provide additional information about specific edges. unsigned Latency; - /// Record MinLatency seperately from "expected" Latency. - /// - /// FIXME: this field is not packed on LP64. Convert to 16-bit DAG edge - /// latency after introducing saturating truncation. - unsigned MinLatency; public: /// SDep - Construct a null SDep. This is only for use by container @@ -120,10 +115,9 @@ namespace llvm { Latency = 1; break; } - MinLatency = Latency; } SDep(SUnit *S, OrderKind kind) - : Dep(S, Order), Contents(), Latency(0), MinLatency(0) { + : Dep(S, Order), Contents(), Latency(0) { Contents.OrdKind = kind; } @@ -142,8 +136,7 @@ namespace llvm { } bool operator==(const SDep &Other) const { - return overlaps(Other) - && Latency == Other.Latency && MinLatency == Other.MinLatency; + return overlaps(Other) && Latency == Other.Latency; } bool operator!=(const SDep &Other) const { @@ -163,18 +156,6 @@ namespace llvm { Latency = Lat; } - /// getMinLatency - Return the minimum latency for this edge. Minimum - /// latency is used for scheduling groups, while normal (expected) latency - /// is for instruction cost and critical path. - unsigned getMinLatency() const { - return MinLatency; - } - - /// setMinLatency - Set the minimum latency for this edge. - void setMinLatency(unsigned Lat) { - MinLatency = Lat; - } - //// getSUnit - Return the SUnit to which this edge points. SUnit *getSUnit() const { return Dep.getPointer(); @@ -267,7 +248,7 @@ namespace llvm { /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: - enum { BoundaryID = ~0u }; + enum LLVM_ENUM_INT_TYPE(unsigned) { BoundaryID = ~0u }; SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. @@ -282,10 +263,10 @@ namespace llvm { 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; + typedef SmallVectorImpl::iterator pred_iterator; + typedef SmallVectorImpl::iterator succ_iterator; + typedef SmallVectorImpl::const_iterator const_pred_iterator; + typedef SmallVectorImpl::const_iterator const_succ_iterator; unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 990cac6348b1e..fe4f3c2de3b6b 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -28,6 +28,7 @@ namespace llvm { class MachineDominatorTree; class LiveIntervals; class RegPressureTracker; + class PressureDiffs; /// An individual mapping from virtual register number to SUnit. struct VReg2SUnit { @@ -56,7 +57,8 @@ namespace llvm { /// Use a SparseMultiSet to track physical registers. Storage is only /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. - typedef SparseMultiSet, uint16_t> Reg2SUnitsMap; + typedef SparseMultiSet, uint16_t> + Reg2SUnitsMap; /// Use SparseSet as a SparseMap by relying on the fact that it never /// compares ValueT's, only unsigned keys. This allows the set to be cleared @@ -64,6 +66,11 @@ namespace llvm { /// require a destructor. typedef SparseSet VReg2SUnitMap; + /// Track local uses of virtual registers. These uses are gathered by the DAG + /// builder and may be consulted by the scheduler to avoid iterating an entire + /// vreg use list. + typedef SparseMultiSet VReg2UseMap; + /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of /// MachineInstrs. class ScheduleDAGInstrs : public ScheduleDAG { @@ -81,10 +88,6 @@ namespace llvm { /// isPostRA flag indicates vregs cannot be present. bool IsPostRA; - /// UnitLatencies (misnamed) flag avoids computing def-use latencies, using - /// the def-side latency only. - bool UnitLatencies; - /// The standard DAG builder does not normally include terminators as DAG /// nodes because it does not create the necessary dependencies to prevent /// reordering. A specialized scheduler can overide @@ -104,17 +107,18 @@ namespace llvm { /// The end of the range to be scheduled. MachineBasicBlock::iterator RegionEnd; - /// The index in BB of RegionEnd. - /// - /// This is the instruction number from the top of the current block, not - /// the SlotIndex. It is only used by the AntiDepBreaker and should be - /// removed once that client is obsolete. - unsigned EndIndex; + /// Instructions in this region (distance(RegionBegin, RegionEnd)). + unsigned NumRegionInstrs; /// After calling BuildSchedGraph, each machine instruction in the current /// scheduling region is mapped to an SUnit. DenseMap MISUnitMap; + /// After calling BuildSchedGraph, each vreg used in the scheduling region + /// is mapped to a set of SUnits. These include all local vreg uses, not + /// just the uses for a singly defined vreg. + VReg2UseMap VRegUses; + /// State internal to DAG building. /// ------------------------------- @@ -125,7 +129,7 @@ namespace llvm { Reg2SUnitsMap Defs; Reg2SUnitsMap Uses; - /// Track the last instructon in this region defining each virtual register. + /// Track the last instruction in this region defining each virtual register. VReg2SUnitMap VRegDefs; /// PendingLoads - Remember where unknown loads are after the most recent @@ -158,7 +162,7 @@ namespace llvm { /// \brief Resolve and cache a resolved scheduling class for an SUnit. const MCSchedClassDesc *getSchedClass(SUnit *SU) const { - if (!SU->SchedClass) + if (!SU->SchedClass && SchedModel.hasInstrSchedModel()) SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); return SU->SchedClass; } @@ -185,14 +189,15 @@ namespace llvm { virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); + unsigned regioninstrs); /// Notify that the scheduler has finished scheduling the current region. virtual void exitRegion(); /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0); + void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0, + PressureDiffs *PDiffs = 0); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 8c064bf2d446e..82becca315a14 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -33,12 +33,50 @@ class AliasAnalysis; class MachineConstantPoolValue; class MachineFunction; class MDNode; -class SDNodeOrdering; class SDDbgValue; class TargetLowering; class TargetSelectionDAGInfo; class TargetTransformInfo; +class SDVTListNode : public FoldingSetNode { + friend struct FoldingSetTrait; + /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// The Allocator in SelectionDAG holds the data. + /// SDVTList contains all types which are frequently accessed in SelectionDAG. + /// The size of this list is not expected big so it won't introduce memory penalty. + FoldingSetNodeIDRef FastID; + const EVT *VTs; + unsigned int NumVTs; + /// The hash value for SDVTList is fixed so cache it to avoid hash calculation + unsigned HashValue; +public: + SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : + FastID(ID), VTs(VT), NumVTs(Num) { + HashValue = ID.ComputeHash(); + } + SDVTList getSDVTList() { + SDVTList result = {VTs, NumVTs}; + return result; + } +}; + +// Specialize FoldingSetTrait for SDVTListNode +// To avoid computing temp FoldingSetNodeID and hash value. +template<> struct FoldingSetTrait : DefaultFoldingSetTrait { + static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { + ID = X.FastID; + } + static bool Equals(const SDVTListNode &X, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) { + if (X.HashValue != IDHash) + return false; + return ID == X.FastID; + } + static unsigned ComputeHash(const SDVTListNode &X, FoldingSetNodeID &TempID) { + return X.HashValue; + } +}; + template<> struct ilist_traits : public ilist_default_traits { private: mutable ilist_half_node Sentinel; @@ -73,7 +111,8 @@ private: class SDDbgInfo { SmallVector DbgValues; SmallVector ByvalParmDbgValues; - DenseMap > DbgValMap; + typedef DenseMap > DbgValMapType; + DbgValMapType DbgValMap; void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; @@ -99,14 +138,13 @@ public: } ArrayRef getSDDbgValues(const SDNode *Node) { - DenseMap >::iterator I = - DbgValMap.find(Node); + DbgValMapType::iterator I = DbgValMap.find(Node); if (I != DbgValMap.end()) return I->second; return ArrayRef(); } - typedef SmallVector::iterator DbgIterator; + typedef SmallVectorImpl::iterator DbgIterator; DbgIterator DbgBegin() { return DbgValues.begin(); } DbgIterator DbgEnd() { return DbgValues.end(); } DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } @@ -130,9 +168,9 @@ void checkForCycles(const SelectionDAG *DAG); /// class SelectionDAG { const TargetMachine &TM; - const TargetLowering &TLI; const TargetSelectionDAGInfo &TSI; const TargetTransformInfo *TTI; + const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; CodeGenOpt::Level OptLevel; @@ -166,10 +204,6 @@ class SelectionDAG { /// 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; @@ -203,6 +237,13 @@ public: virtual void NodeUpdated(SDNode *N); }; + /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to + /// ensure that getConstant() and similar functions return DAG nodes that + /// have legal types. This is important after type legalization since + /// any illegally typed nodes generated after this point will not experience + /// type legalization. + bool NewNodesMustHaveLegalTypes; + private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. friend struct DAGUpdateListener; @@ -228,7 +269,8 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetTransformInfo *TTI); + void init(MachineFunction &mf, const TargetTransformInfo *TTI, + const TargetLowering *TLI); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -237,7 +279,7 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } - const TargetLowering &getTargetLoweringInfo() const { return TLI; } + const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } @@ -386,10 +428,10 @@ public: SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { return getConstantFP(Val, VT, true); } - SDValue getGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, bool isTargetGA = false, unsigned char TargetFlags = 0); - SDValue getTargetGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + SDValue getTargetGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, unsigned char TargetFlags = 0) { return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags); @@ -424,15 +466,15 @@ public: // 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 getBasicBlock(MachineBasicBlock *MBB, SDLoc dl); SDValue getExternalSymbol(const char *Sym, EVT VT); - SDValue getExternalSymbol(const char *Sym, DebugLoc dl, EVT VT); + SDValue getExternalSymbol(const char *Sym, SDLoc dl, EVT VT); SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags = 0); SDValue getValueType(EVT); SDValue getRegister(unsigned Reg, EVT VT); SDValue getRegisterMask(const uint32_t *RegMask); - SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label); + SDValue getEHLabel(SDLoc dl, SDValue Root, MCSymbol *Label); SDValue getBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset = 0, bool isTarget = false, unsigned char TargetFlags = 0); @@ -442,7 +484,7 @@ public: return getBlockAddress(BA, VT, Offset, true, TargetFlags); } - SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { + SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N) { return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, getRegister(Reg, N.getValueType()), N); } @@ -450,7 +492,7 @@ public: // 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 getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N, SDValue Glue) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; @@ -458,14 +500,14 @@ public: } // Similar to last getCopyToReg() except parameter Reg is a SDValue - SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, + SDValue getCopyToReg(SDValue Chain, SDLoc 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) { + SDValue getCopyFromReg(SDValue Chain, SDLoc 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); @@ -474,7 +516,7 @@ public: // 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 getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT, SDValue Glue) { SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; @@ -485,7 +527,7 @@ public: /// 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 getConvertRndSat(EVT VT, SDLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); @@ -493,95 +535,95 @@ public: /// 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, + SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. - SDValue getAnyExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); /// 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); + SDValue getSExtOrTrunc(SDValue Op, SDLoc 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); + SDValue getZExtOrTrunc(SDValue Op, SDLoc 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); + SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). - SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); + SDValue getNOT(SDLoc 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) { + /// useful SDLoc. + SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; - return getNode(ISD::CALLSEQ_START, DebugLoc(), VTs, Ops, 2); + return getNode(ISD::CALLSEQ_START, DL, 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. + /// a useful SDLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, - SDValue InGlue) { + SDValue InGlue, SDLoc DL) { 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], + return getNode(ISD::CALLSEQ_END, DL, NodeTys, &Ops[0], (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); } - /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. + /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc. SDValue getUNDEF(EVT VT) { - return getNode(ISD::UNDEF, DebugLoc(), VT); + return getNode(ISD::UNDEF, SDLoc(), VT); } /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does - /// not have a useful DebugLoc. + /// not have a useful SDLoc. SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { - return getNode(ISD::GLOBAL_OFFSET_TABLE, DebugLoc(), VT); + return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), 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 getNode(unsigned Opcode, SDLoc DL, EVT VT); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, const SDUse *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, + SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef ResultTys, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, const EVT *VTs, unsigned NumVTs, + SDValue getNode(unsigned Opcode, SDLoc DL, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc 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 getNode(unsigned Opcode, SDLoc DL, SDVTList VTs); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); @@ -591,36 +633,50 @@ public: /// clobbered. SDValue getStackArgumentTokenFactor(SDValue Chain); - SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue getMemcpy(SDValue Chain, SDLoc 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 getMemmove(SDValue Chain, SDLoc 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 getMemset(SDValue Chain, SDLoc 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, + SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond) { assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() && "Cannot compare scalars to vectors"); assert(LHS.getValueType().isVector() == VT.isVector() && "Cannot compare scalars to vectors"); + assert(Cond != ISD::SETCC_INVALID && + "Cannot create a setCC of an invalid node."); return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } + // getSelect - Helper function to make it easier to build Select's if you just + // have operands and don't want to check for vector. + SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond, + SDValue LHS, SDValue RHS) { + assert(LHS.getValueType() == RHS.getValueType() && + "Cannot use select on differing types"); + assert(VT.isVector() == LHS.getValueType().isVector() && + "Cannot mix vectors and scalars"); + return getNode(Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT, DL, VT, + Cond, LHS, RHS); + } + /// 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 getSelectCC(SDLoc 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)); @@ -628,17 +684,17 @@ public: /// 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 getVAArg(EVT VT, SDLoc 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 getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, AtomicOrdering Ordering, @@ -646,93 +702,105 @@ public: /// getAtomic - Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* PtrVal, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 1 operand. - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, EVT VT, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, const Value* PtrVal, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, EVT VT, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes N operands. + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, + SDValue* Ops, unsigned NumOps, MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); + /// 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, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc 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, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc 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, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc 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); + SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, SDLoc 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, + SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); - SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + MachineMemOperand *MMO); + SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc 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 getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, EVT MemVT, + MachineMemOperand *MMO); + SDValue getIndexedLoad(SDValue OrigLoad, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, - EVT VT, DebugLoc dl, + EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, - EVT VT, DebugLoc dl, + EVT VT, SDLoc 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, + SDValue getStore(SDValue Chain, SDLoc 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, + SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); - SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + SDValue getTruncStore(SDValue Chain, SDLoc 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, + SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); - SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, + SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); /// getSrcValue - Construct a node to track a Value* through the backend. @@ -741,6 +809,10 @@ public: /// getMDNode - Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); + /// getAddrSpaceCast - Return an AddrSpaceCastSDNode. + SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, + unsigned SrcAS, unsigned DestAS); + /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); @@ -804,47 +876,47 @@ public: /// 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, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT); + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2); + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, EVT VT4, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, ArrayRef ResultTys, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs, ArrayRef Ops); /// getTargetExtractSubreg - A convenience function for creating /// TargetInstrInfo::EXTRACT_SUBREG nodes. - SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand); /// getTargetInsertSubreg - A convenience function for creating /// TargetInstrInfo::INSERT_SUBREG nodes. - SDValue getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand, SDValue Subreg); /// getNodeIfExists - Get the specified node if it's already available, or @@ -950,12 +1022,6 @@ public: } } - /// 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); @@ -998,7 +1064,7 @@ public: /// FoldSetCC - Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, - SDValue N2, ISD::CondCode Cond, DebugLoc dl); + SDValue N2, ISD::CondCode Cond, SDLoc dl); /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We /// use this predicate to simplify operations downstream. @@ -1064,6 +1130,30 @@ public: /// it cannot be inferred. unsigned InferPtrAlignment(SDValue Ptr) const; + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + std::pair GetSplitDestVTs(const EVT &VT) const; + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides + /// VTs and return the low/high part. + std::pair SplitVector(const SDValue &N, const SDLoc &DL, + const EVT &LoVT, const EVT &HiVT); + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the + /// low/high part. + std::pair SplitVector(const SDValue &N, const SDLoc &DL) { + EVT LoVT, HiVT; + llvm::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); + return SplitVector(N, DL, LoVT, HiVT); + } + + /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and + /// return the low/high part. + std::pair SplitVectorOperand(const SDNode *N, unsigned OpNo) + { + return SplitVector(N->getOperand(OpNo), SDLoc(N)); + } + private: bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); @@ -1072,7 +1162,7 @@ private: void *&InsertPos); SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps, void *&InsertPos); - SDNode *UpdadeDebugLocOnMergedSDNode(SDNode *N, DebugLoc loc); + SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, SDLoc loc); void DeleteNodeNotInCSEMaps(SDNode *N); void DeallocateNode(SDNode *N); @@ -1082,7 +1172,7 @@ private: void allnodes_clear(); /// VTList - List of non-single value types. - std::vector VTList; + FoldingSet VTListMap; /// CondCodeNodes - Maps to auto-CSE operations. std::vector CondCodeNodes; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index a4721db6851f0..b5ec8cb075dca 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -30,7 +30,6 @@ namespace llvm { class MachineInstr; class TargetLowering; class TargetLibraryInfo; - class TargetInstrInfo; class TargetTransformInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; @@ -42,8 +41,7 @@ namespace llvm { /// pattern-matching instruction selectors. class SelectionDAGISel : public MachineFunctionPass { public: - const TargetMachine &TM; - const TargetLowering &TLI; + TargetMachine &TM; const TargetLibraryInfo *LibInfo; const TargetTransformInfo *TTI; FunctionLoweringInfo *FuncInfo; @@ -56,11 +54,13 @@ public: CodeGenOpt::Level OptLevel; static char ID; - explicit SelectionDAGISel(const TargetMachine &tm, + explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - const TargetLowering &getTargetLowering() { return TLI; } + const TargetLowering *getTargetLowering() const { + return TM.getTargetLowering(); + } virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -113,6 +113,8 @@ public: OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, + OPC_CheckChild0Same, OPC_CheckChild1Same, + OPC_CheckChild2Same, OPC_CheckChild3Same, OPC_CheckPatternPredicate, OPC_CheckPredicate, OPC_CheckOpcode, diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index fef567f56bce2..70c15e6c6e6f7 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -344,6 +344,13 @@ private: /// debugLoc - source line information. DebugLoc debugLoc; + // The ordering of the SDNodes. It roughly corresponds to the ordering of the + // original LLVM instructions. + // This is used for turning off scheduling, because we'll forgo + // the normal scheduling algorithms and output the instructions according to + // this ordering. + unsigned IROrder; + /// getValueTypeList - Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); @@ -365,7 +372,7 @@ public: /// \ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } - /// isTargetMemoryOpcode - Test if this node has a target-specific + /// 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 { @@ -412,6 +419,14 @@ public: /// setNodeId - Set unique node id. void setNodeId(int Id) { NodeId = Id; } + /// getIROrder - Return the node ordering. + /// + unsigned getIROrder() const { return IROrder; } + + /// setIROrder - Set the node ordering. + /// + void setIROrder(unsigned Order) { IROrder = Order; } + /// getDebugLoc - Return the source location info. const DebugLoc getDebugLoc() const { return debugLoc; } @@ -505,7 +520,9 @@ public: /// isPredecessorOf - Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as /// expensive. Use carefully. - bool isPredecessorOf(const SDNode *N) const { return N->hasPredecessor(this); } + bool isPredecessorOf(const SDNode *N) const { + return N->hasPredecessor(this); + } /// hasPredecessor - Return true if N is a predecessor of this node. /// N is either an operand of this node, or can be reached by recursively @@ -524,7 +541,7 @@ public: /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, SmallPtrSet &Visited, - SmallVector &Worklist) const; + SmallVectorImpl &Worklist) const; /// getNumOperands - Return the number of values used by this operation. /// @@ -681,14 +698,14 @@ protected: return Ret; } - SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops, - unsigned NumOps) + SDNode(unsigned Opc, unsigned Order, 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) { + debugLoc(dl), IROrder(Order) { for (unsigned i = 0; i != NumOps; ++i) { OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); @@ -698,11 +715,11 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs) + SDNode(unsigned Opc, unsigned Order, 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) {} + SubclassData(0), NodeId(-1), OperandList(0), + ValueList(VTs.VTs), UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(dl), IROrder(Order) {} /// InitOperands - Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { @@ -770,6 +787,53 @@ protected: void DropOperands(); }; +/// Wrapper class for IR location info (IR ordering and DebugLoc) to be passed +/// into SDNode creation functions. +/// When an SDNode is created from the DAGBuilder, the DebugLoc is extracted +/// from the original Instruction, and IROrder is the ordinal position of +/// the instruction. +/// When an SDNode is created after the DAG is being built, both DebugLoc and +/// the IROrder are propagated from the original SDNode. +/// So SDLoc class provides two constructors besides the default one, one to +/// be used by the DAGBuilder, the other to be used by others. +class SDLoc { +private: + // Ptr could be used for either Instruction* or SDNode*. It is used for + // Instruction* if IROrder is not -1. + const void *Ptr; + int IROrder; + +public: + SDLoc() : Ptr(NULL), IROrder(0) {} + SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) { + assert(N && "null SDNode"); + } + SDLoc(const SDValue V) : Ptr(V.getNode()), IROrder(-1) { + assert(Ptr && "null SDNode"); + } + SDLoc(const Instruction *I, int Order) : Ptr(I), IROrder(Order) { + assert(Order >= 0 && "bad IROrder"); + } + unsigned getIROrder() { + if (IROrder >= 0 || Ptr == NULL) { + return (unsigned)IROrder; + } + const SDNode *N = (const SDNode*)(Ptr); + return N->getIROrder(); + } + DebugLoc getDebugLoc() { + if (Ptr == NULL) { + return DebugLoc(); + } + if (IROrder >= 0) { + const Instruction *I = (const Instruction*)(Ptr); + return I->getDebugLoc(); + } + const SDNode *N = (const SDNode*)(Ptr); + return N->getDebugLoc(); + } +}; + // Define inline functions from the SDValue class. @@ -839,8 +903,9 @@ inline void SDUse::setNode(SDNode *N) { class UnarySDNode : public SDNode { SDUse Op; public: - UnarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X) - : SDNode(Opc, dl, VTs) { + UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X) + : SDNode(Opc, Order, dl, VTs) { InitOperands(&Op, X); } }; @@ -850,8 +915,9 @@ public: class BinarySDNode : public SDNode { SDUse Ops[2]; public: - BinarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) - : SDNode(Opc, dl, VTs) { + BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) + : SDNode(Opc, Order, dl, VTs) { InitOperands(Ops, X, Y); } }; @@ -861,9 +927,9 @@ public: 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) { + TernarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y, SDValue Z) + : SDNode(Opc, Order, dl, VTs) { InitOperands(Ops, X, Y, Z); } }; @@ -876,20 +942,31 @@ public: 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)) { + : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) { InitOperands(&Op, X); } ~HandleSDNode(); const SDValue &getValue() const { return Op; } }; +class AddrSpaceCastSDNode : public UnarySDNode { +private: + unsigned SrcAddrSpace; + unsigned DestAddrSpace; + +public: + AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X, + unsigned SrcAS, unsigned DestAS); + + unsigned getSrcAddressSpace() const { return SrcAddrSpace; } + unsigned getDestAddressSpace() const { return DestAddrSpace; } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ADDRSPACECAST; + } +}; + /// Abstact virtual class for operations for memory operations class MemSDNode : public SDNode { private: @@ -901,17 +978,18 @@ protected: MachineMemOperand *MMO; public: - MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, - MachineMemOperand *MMO); + MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + EVT MemoryVT, MachineMemOperand *MMO); - MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, + MemSDNode(unsigned Opc, unsigned Order, 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 { + unsigned getOriginalAlignment() const { return MMO->getBaseAlignment(); } unsigned getAlignment() const { @@ -1028,30 +1106,43 @@ public: // 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, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Val); } - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr); } + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue* AllOps, SDUse *DynOps, unsigned NumOps, + MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + InitAtomic(Ordering, SynchScope); + assert((DynOps || NumOps <= array_lengthof(Ops)) && + "Too many ops for internal storage!"); + InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1086,10 +1177,10 @@ public: /// with a value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { public: - MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO) - : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { + : MemSDNode(Opc, Order, dl, VTs, Ops, NumOps, MemoryVT, MMO) { } // Methods to support isa and dyn_cast @@ -1119,9 +1210,9 @@ class ShuffleVectorSDNode : public SDNode { 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) { + ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1, + SDValue N2, const int *M) + : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) { InitOperands(Ops, N1, N2); } public: @@ -1134,16 +1225,16 @@ public: assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); return Mask[Idx]; } - + bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() const { + 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) + if (Mask[i] >= 0) return Mask[i]; } - return -1; + llvm_unreachable("Splat with all undef indices?"); } static bool isSplatMask(const int *Mask, EVT VT); @@ -1151,13 +1242,13 @@ public: 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) { + 0, DebugLoc(), getSDVTList(VT)), Value(val) { } public: @@ -1181,7 +1272,7 @@ class ConstantFPSDNode : public SDNode { friend class SelectionDAG; ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DebugLoc(), getSDVTList(VT)), Value(val) { } public: @@ -1224,8 +1315,9 @@ class GlobalAddressSDNode : public SDNode { 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); + GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL, + const GlobalValue *GA, EVT VT, int64_t o, + unsigned char TargetFlags); public: const GlobalValue *getGlobal() const { return TheGlobal; } @@ -1247,7 +1339,7 @@ class FrameIndexSDNode : public SDNode { friend class SelectionDAG; FrameIndexSDNode(int fi, EVT VT, bool isTarg) : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, - DebugLoc(), getSDVTList(VT)), FI(fi) { + 0, DebugLoc(), getSDVTList(VT)), FI(fi) { } public: @@ -1265,7 +1357,7 @@ class JumpTableSDNode : public SDNode { 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) { + 0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { } public: @@ -1289,23 +1381,22 @@ class ConstantPoolSDNode : public SDNode { 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) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(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) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(Offset >= 0 && "Offset is too large"); Val.MachineCPVal = v; Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); } public: - bool isMachineConstantPoolEntry() const { return Offset < 0; @@ -1347,7 +1438,7 @@ class TargetIndexSDNode : public SDNode { public: TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF) - : SDNode(ISD::TargetIndex, DebugLoc(), getSDVTList(VT)), + : SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)), TargetFlags(TF), Index(Idx), Offset(Ofs) {} public: @@ -1367,8 +1458,8 @@ class BasicBlockSDNode : public SDNode { /// 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) { - } + : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) + {} public: MachineBasicBlock *getBasicBlock() const { return MBB; } @@ -1411,7 +1502,7 @@ class SrcValueSDNode : public SDNode { friend class SelectionDAG; /// Create a SrcValue for a general value. explicit SrcValueSDNode(const Value *v) - : SDNode(ISD::SRCVALUE, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} + : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} public: /// getValue - return the contained Value. @@ -1421,27 +1512,27 @@ public: 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) {} + : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) + {} public: - + const MDNode *getMD() const { return MD; } - + 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) { + : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) { } public: @@ -1457,7 +1548,7 @@ class RegisterMaskSDNode : public SDNode { const uint32_t *RegMask; friend class SelectionDAG; RegisterMaskSDNode(const uint32_t *mask) - : SDNode(ISD::RegisterMask, DebugLoc(), getSDVTList(MVT::Untyped)), + : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)), RegMask(mask) {} public: @@ -1475,7 +1566,7 @@ class BlockAddressSDNode : public SDNode { friend class SelectionDAG; BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, int64_t o, unsigned char Flags) - : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), + : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), BA(ba), Offset(o), TargetFlags(Flags) { } public: @@ -1493,8 +1584,8 @@ 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) { + EHLabelSDNode(unsigned Order, DebugLoc dl, SDValue ch, MCSymbol *L) + : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) { InitOperands(&Chain, ch); } public: @@ -1508,11 +1599,11 @@ public: 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) { + 0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { } public: @@ -1529,7 +1620,7 @@ class CondCodeSDNode : public SDNode { ISD::CondCode Condition; friend class SelectionDAG; explicit CondCodeSDNode(ISD::CondCode Cond) - : SDNode(ISD::CONDCODE, DebugLoc(), getSDVTList(MVT::Other)), + : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)), Condition(Cond) { } public: @@ -1540,15 +1631,16 @@ public: 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), + explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, + const SDValue *Ops, unsigned NumOps, + ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops, NumOps), CvtCode(Code) { assert(NumOps == 5 && "wrong number of operations"); } @@ -1566,7 +1658,7 @@ class VTSDNode : public SDNode { EVT ValueType; friend class SelectionDAG; explicit VTSDNode(EVT VT) - : SDNode(ISD::VALUETYPE, DebugLoc(), getSDVTList(MVT::Other)), + : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)), ValueType(VT) { } public: @@ -1589,10 +1681,11 @@ class LSBaseSDNode : public MemSDNode { */ 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) { + LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, + MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); InitOperands(Ops, Operands, numOperands); @@ -1626,11 +1719,10 @@ public: /// class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; - LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, + LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs, ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, - VTs, AM, MemVT, MMO) { + : LSBaseSDNode(ISD::LOAD, Order, 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!"); @@ -1656,10 +1748,10 @@ public: /// class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; - StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl, + SDVTList VTs, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, + : LSBaseSDNode(ISD::STORE, Order, dl, ChainValuePtrOff, 4, VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); @@ -1692,8 +1784,8 @@ public: private: friend class SelectionDAG; - MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) - : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, Order, DL, VTs), MemRefs(0), MemRefsEnd(0) {} /// LocalOperands - Operands for this instruction, if they fit here. If /// they don't, this field is unused. @@ -1781,7 +1873,7 @@ template <> struct GraphTraits { /// LargestSDNode - The largest SDNode class. /// -typedef LoadSDNode LargestSDNode; +typedef AtomicSDNode LargestSDNode; /// MostAlignedSDNode - The SDNode class with the greatest alignment /// requirement. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 26d0433f3e87c..984796af8644e 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -59,7 +59,7 @@ namespace llvm { // poisoned, so that dangling SlotIndex access can be reliably detected. void setPoison() { intptr_t tmp = reinterpret_cast(mi); - assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); + assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); tmp |= 0x1; mi = reinterpret_cast(tmp); } @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - operator bool() const { return isValid(); } + LLVM_EXPLICIT operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; @@ -218,6 +218,13 @@ namespace llvm { return other.getIndex() - getIndex(); } + /// Return the scaled distance from this index to the given one, where all + /// slots on the same instruction have zero distance. + int getInstrDistance(SlotIndex other) const { + return (other.listEntry()->getIndex() - listEntry()->getIndex()) + / Slot_Count; + } + /// isBlock - Returns true if this is a block boundary slot. bool isBlock() const { return getSlot() == Slot_Block; } @@ -672,7 +679,7 @@ namespace llvm { /// performance. Any remaining SlotIndex objects that point to the same /// index are left 'dangling' (much the same as a dangling pointer to a /// freed object) and should not be accessed, except to destruct them. - /// + /// /// Like dangling pointers, access to dangling SlotIndexes can cause /// painful-to-track-down bugs, especially if the memory for the index /// previously pointed to has been re-used. To detect dangling SlotIndex diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h new file mode 100644 index 0000000000000..e90f22e5b69a6 --- /dev/null +++ b/include/llvm/CodeGen/StackMaps.h @@ -0,0 +1,175 @@ +//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_STACKMAPS +#define LLVM_STACKMAPS + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstr.h" +#include +#include + +namespace llvm { + +class AsmPrinter; +class MCExpr; + +/// \brief MI-level patchpoint operands. +/// +/// MI patchpoint operations take the form: +/// [], , , , , , ... +/// +/// IR patchpoint intrinsics do not have the operand because calling +/// convention is part of the subclass data. +/// +/// SD patchpoint nodes do not have a def operand because it is part of the +/// SDValue. +/// +/// Patchpoints following the anyregcc convention are handled specially. For +/// these, the stack map also records the location of the return value and +/// arguments. +class PatchPointOpers { +public: + /// Enumerate the meta operands. + enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; +private: + const MachineInstr *MI; + bool HasDef; + bool IsAnyReg; +public: + explicit PatchPointOpers(const MachineInstr *MI); + + bool isAnyReg() const { return IsAnyReg; } + bool hasDef() const { return HasDef; } + + unsigned getMetaIdx(unsigned Pos = 0) const { + assert(Pos < MetaEnd && "Meta operand index out of range."); + return (HasDef ? 1 : 0) + Pos; + } + + const MachineOperand &getMetaOper(unsigned Pos) { + return MI->getOperand(getMetaIdx(Pos)); + } + + unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } + + /// Get the operand index of the variable list of non-argument operands. + /// These hold the "live state". + unsigned getVarIdx() const { + return getMetaIdx() + MetaEnd + + MI->getOperand(getMetaIdx(NArgPos)).getImm(); + } + + /// Get the index at which stack map locations will be recorded. + /// Arguments are not recorded unless the anyregcc convention is used. + unsigned getStackMapStartIdx() const { + if (IsAnyReg) + return getArgIdx(); + return getVarIdx(); + } + + /// \brief Get the next scratch register operand index. + unsigned getNextScratchIdx(unsigned StartIdx = 0) const; +}; + +class StackMaps { +public: + struct Location { + enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, + ConstantIndex }; + LocationType LocType; + unsigned Size; + unsigned Reg; + int64_t Offset; + Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} + Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) + : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} + }; + + // Typedef a function pointer for functions that parse sequences of operands + // and return a Location, plus a new "next" operand iterator. + typedef std::pair + (*OperandParser)(MachineInstr::const_mop_iterator, + MachineInstr::const_mop_iterator, const TargetMachine&); + + // OpTypes are used to encode information about the following logical + // operand (which may consist of several MachineOperands) for the + // OpParser. + typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; + + StackMaps(AsmPrinter &AP, OperandParser OpParser) + : AP(AP), OpParser(OpParser) {} + + /// \brief Generate a stackmap record for a stackmap instruction. + /// + /// MI must be a raw STACKMAP, not a PATCHPOINT. + void recordStackMap(const MachineInstr &MI); + + /// \brief Generate a stackmap record for a patchpoint instruction. + void recordPatchPoint(const MachineInstr &MI); + + /// If there is any stack map data, create a stack map section and serialize + /// the map info into it. This clears the stack map data structures + /// afterwards. + void serializeToStackMapSection(); + +private: + typedef SmallVector LocationVec; + + struct CallsiteInfo { + const MCExpr *CSOffsetExpr; + unsigned ID; + LocationVec Locations; + CallsiteInfo() : CSOffsetExpr(0), ID(0) {} + CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, + LocationVec Locations) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} + }; + + typedef std::vector CallsiteInfoList; + + struct ConstantPool { + private: + typedef std::map ConstantsMap; + std::vector ConstantsList; + ConstantsMap ConstantIndexes; + + public: + size_t getNumConstants() const { return ConstantsList.size(); } + int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; } + size_t getConstantIndex(int64_t ConstVal) { + size_t NextIdx = ConstantsList.size(); + ConstantsMap::const_iterator I = + ConstantIndexes.insert(ConstantIndexes.end(), + std::make_pair(ConstVal, NextIdx)); + if (I->second == NextIdx) + ConstantsList.push_back(ConstVal); + return I->second; + } + }; + + AsmPrinter &AP; + OperandParser OpParser; + CallsiteInfoList CSInfos; + ConstantPool ConstPool; + + /// This should be called by the MC lowering code _immediately_ before + /// lowering the MI to an MCInst. It records where the operands for the + /// instruction are stored, and outputs a label to record the offset of + /// the call from the start of the text section. In special cases (e.g. AnyReg + /// calling convention) the return register is also recorded if requested. + void recordStackMapOpers(const MachineInstr &MI, uint32_t ID, + MachineInstr::const_mop_iterator MOI, + MachineInstr::const_mop_iterator MOE, + bool recordResult = false); +}; + +} + +#endif // LLVM_STACKMAPS diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h new file mode 100644 index 0000000000000..d09a933a663b4 --- /dev/null +++ b/include/llvm/CodeGen/StackProtector.h @@ -0,0 +1,127 @@ +//===-- StackProtector.h - 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKPROTECTOR_H +#define LLVM_CODEGEN_STACKPROTECTOR_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { +class DominatorTree; +class Function; +class Module; +class PHINode; + +class StackProtector : public FunctionPass { +public: + /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that + /// vulnerable stack allocations are located close the stack protector. + enum SSPLayoutKind { + SSPLK_None, ///< Did not trigger a stack protector. No effect on data + ///< layout. + SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest + ///< to the stack protector. + SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest + ///< to the stack protector. + SSPLK_AddrOf ///< The address of this allocation is exposed and + ///< triggered protection. 3rd closest to the protector. + }; + + /// A mapping of AllocaInsts to their required SSP layout. + typedef ValueMap SSPLayoutMap; + +private: + const TargetMachine *TM; + + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLoweringBase *TLI; + const Triple Trip; + + Function *F; + Module *M; + + DominatorTree *DT; + + /// Layout - Mapping of allocations to the required SSPLayoutKind. + /// StackProtector analysis will update this map when determining if an + /// AllocaInst triggers a stack protector. + SSPLayoutMap Layout; + + /// \brief The minimum size of buffers that will receive stack smashing + /// protection when -fstack-protection is used. + unsigned SSPBufferSize; + + /// VisitedPHIs - The set of PHI nodes visited when determining + /// if a variable's reference has been taken. This set + /// is maintained to ensure we don't visit the same PHI node multiple + /// times. + SmallPtrSet VisitedPHIs; + + /// 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(); + + /// ContainsProtectableArray - Check whether the type either is an array or + /// contains an array of sufficient size so that we need stack protectors + /// for it. + /// \param [out] IsLarge is set to true if a protectable array is found and + /// it is "large" ( >= ssp-buffer-size). In the case of a structure with + /// multiple arrays, this gets set if any of them is large. + bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false, + bool InStruct = false) const; + + /// \brief Check whether a stack allocation has its address taken. + bool HasAddressTaken(const Instruction *AI); + + /// RequiresStackProtector - Check whether or not this function needs a + /// stack protector based upon the stack protector level. + bool RequiresStackProtector(); + +public: + static char ID; // Pass identification, replacement for typeid. + StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + StackProtector(const TargetMachine *TM) + : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()), + SSPBufferSize(8) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } + + SSPLayoutKind getSSPLayout(const AllocaInst *AI) const; + + virtual bool runOnFunction(Function &Fn); +}; +} // end namespace llvm + +#endif // LLVM_CODEGEN_STACKPROTECTOR_H diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 3e22252eeac13..8ef26b7ca5480 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -84,9 +84,6 @@ public: /// \brief Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } - /// \brief Number of cycles the OOO processor is expected to hide. - unsigned getILPWindow() const { return SchedModel.ILPWindow; } - /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = 0) const; @@ -131,18 +128,23 @@ public: return ResourceLCM; } + /// \brief Number of micro-ops that may be buffered for OOO execution. + unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; } + + /// \brief Number of resource units that may be buffered for OOO execution. + /// \return The buffer size in resource units or -1 for unlimited. + int getResourceBufferSize(unsigned PIdx) const { + return SchedModel.getProcResource(PIdx)->BufferSize; + } + /// \brief Compute operand latency based on the available machine model. /// - /// Computes and return the latency of the given data dependent def and use + /// Compute and return the latency of the given data dependent def and use /// when the operand indices are already known. UseMI may be NULL for an /// unknown user. - /// - /// FindMin may be set to get the minimum vs. expected latency. Minimum - /// latency is used for scheduling groups, while expected latency is for - /// instruction cost and critical path. unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, - const MachineInstr *UseMI, unsigned UseOperIdx, - bool FindMin) const; + const MachineInstr *UseMI, unsigned UseOperIdx) + const; /// \brief Compute the instruction latency based on the available machine /// model. @@ -150,19 +152,19 @@ public: /// Compute and return the expected latency of this instruction independent of /// a particular use. computeOperandLatency is the prefered API, but this is /// occasionally useful to help estimate instruction cost. - unsigned computeInstrLatency(const MachineInstr *MI) const; + /// + /// If UseDefaultDefLatency is false and no new machine sched model is + /// present this method falls back to TII->getInstrLatency with an empty + /// instruction itinerary (this is so we preserve the previous behavior of the + /// if converter after moving it to TargetSchedModel). + unsigned computeInstrLatency(const MachineInstr *MI, + bool UseDefaultDefLatency = true) const; /// \brief Output dependency latency of a pair of defs of the same register. /// /// This is typically one cycle. unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DepMI) const; - -private: - /// getDefLatency is a helper for computeOperandLatency. Return the - /// instruction's latency if operand lookup is not required. - /// Otherwise return -1. - int getDefLatency(const MachineInstr *DefMI, bool FindMin) const; }; } // namespace llvm diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index ec48b67b993c2..79f323341fd07 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -27,9 +27,9 @@ namespace llvm { 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. + /// 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 an MVT. class MVT { public: enum SimpleValueType { @@ -67,40 +67,45 @@ namespace llvm { v32i1 = 17, // 32 x i1 v64i1 = 18, // 64 x i1 - v2i8 = 19, // 2 x i8 - v4i8 = 20, // 4 x i8 - v8i8 = 21, // 8 x i8 - v16i8 = 22, // 16 x i8 - v32i8 = 23, // 32 x i8 - v64i8 = 24, // 64 x i8 - v1i16 = 25, // 1 x i16 - v2i16 = 26, // 2 x i16 - v4i16 = 27, // 4 x i16 - v8i16 = 28, // 8 x i16 - v16i16 = 29, // 16 x i16 - v32i16 = 30, // 32 x i16 - v1i32 = 31, // 1 x i32 - v2i32 = 32, // 2 x i32 - v4i32 = 33, // 4 x i32 - v8i32 = 34, // 8 x i32 - v16i32 = 35, // 16 x i32 - v1i64 = 36, // 1 x i64 - v2i64 = 37, // 2 x i64 - v4i64 = 38, // 4 x i64 - v8i64 = 39, // 8 x i64 - v16i64 = 40, // 16 x i64 + v1i8 = 19, // 1 x i8 + v2i8 = 20, // 2 x i8 + v4i8 = 21, // 4 x i8 + v8i8 = 22, // 8 x i8 + v16i8 = 23, // 16 x i8 + v32i8 = 24, // 32 x i8 + v64i8 = 25, // 64 x i8 + v1i16 = 26, // 1 x i16 + v2i16 = 27, // 2 x i16 + v4i16 = 28, // 4 x i16 + v8i16 = 29, // 8 x i16 + v16i16 = 30, // 16 x i16 + v32i16 = 31, // 32 x i16 + v1i32 = 32, // 1 x i32 + v2i32 = 33, // 2 x i32 + v4i32 = 34, // 4 x i32 + v8i32 = 35, // 8 x i32 + v16i32 = 36, // 16 x i32 + v1i64 = 37, // 1 x i64 + v2i64 = 38, // 2 x i64 + v4i64 = 39, // 4 x i64 + v8i64 = 40, // 8 x i64 + v16i64 = 41, // 16 x i64 FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - v2f16 = 41, // 2 x f16 - v2f32 = 42, // 2 x f32 - v4f32 = 43, // 4 x f32 - v8f32 = 44, // 8 x f32 - v16f32 = 45, // 16 x f32 - v2f64 = 46, // 2 x f64 - v4f64 = 47, // 4 x f64 - v8f64 = 48, // 8 x f64 + v2f16 = 42, // 2 x f16 + v4f16 = 43, // 4 x f16 + v8f16 = 44, // 8 x f16 + v1f32 = 45, // 1 x f32 + v2f32 = 46, // 2 x f32 + v4f32 = 47, // 4 x f32 + v8f32 = 48, // 8 x f32 + v16f32 = 49, // 16 x f32 + v1f64 = 50, // 1 x f64 + v2f64 = 51, // 2 x f64 + v4f64 = 52, // 4 x f64 + v8f64 = 53, // 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v8f64, @@ -108,17 +113,17 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i1, LAST_VECTOR_VALUETYPE = v8f64, - x86mmx = 49, // This is an X86 MMX value + x86mmx = 54, // This is an X86 MMX value - Glue = 50, // This glues nodes together during pre-RA sched + Glue = 55, // This glues nodes together during pre-RA sched - isVoid = 51, // This has no value + isVoid = 56, // This has no value - Untyped = 52, // This value takes a register, but has + Untyped = 57, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - LAST_VALUETYPE = 53, // This always remains at the end of the list. + LAST_VALUETYPE = 58, // 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 @@ -203,7 +208,7 @@ namespace llvm { bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v2f32); + SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); } /// is128BitVector - Return true if this is a 128-bit vector type. @@ -265,6 +270,7 @@ namespace llvm { case v16i1 : case v32i1 : case v64i1: return i1; + case v1i8 : case v2i8 : case v4i8 : case v8i8 : @@ -287,11 +293,15 @@ namespace llvm { case v4i64: case v8i64: case v16i64: return i64; - case v2f16: return f16; + case v2f16: + case v4f16: + case v8f16: return f16; + case v1f32: case v2f32: case v4f32: case v8f32: case v16f32: return f32; + case v1f64: case v2f64: case v4f64: case v8f64: return f64; @@ -318,6 +328,7 @@ namespace llvm { case v8i16: case v8i32: case v8i64: + case v8f16: case v8f32: case v8f64: return 8; case v4i1: @@ -325,6 +336,7 @@ namespace llvm { case v4i16: case v4i32: case v4i64: + case v4f16: case v4f32: case v4f64: return 4; case v2i1: @@ -335,14 +347,21 @@ namespace llvm { case v2f16: case v2f32: case v2f64: return 2; + case v1i8: case v1i16: case v1i32: - case v1i64: return 1; + case v1i64: + case v1f32: + case v1f64: return 1; } } unsigned getSizeInBits() const { switch (SimpleTy) { + default: + llvm_unreachable("getSizeInBits called on extended MVT."); + case Other: + llvm_unreachable("Value type is non-standard value, Other."); case iPTR: llvm_unreachable("Value type size is target-dependent. Ask TLI."); case iPTRAny: @@ -352,12 +371,11 @@ namespace llvm { llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); - default: - llvm_unreachable("getSizeInBits called on extended MVT."); case i1 : return 1; case v2i1: return 2; case v4i1: return 4; case i8 : + case v1i8: case v8i1: return 8; case i16 : case f16: @@ -370,6 +388,7 @@ namespace llvm { case v4i8: case v2i16: case v2f16: + case v1f32: case v1i32: return 32; case x86mmx: case f64 : @@ -379,7 +398,9 @@ namespace llvm { case v4i16: case v2i32: case v1i64: - case v2f32: return 64; + case v4f16: + case v2f32: + case v1f64: return 64; case f80 : return 80; case f128: case ppcf128: @@ -388,6 +409,7 @@ namespace llvm { case v8i16: case v4i32: case v2i64: + case v8f16: case v4f32: case v2f64: return 128; case v32i8: @@ -488,6 +510,7 @@ namespace llvm { if (NumElements == 64) return MVT::v64i1; break; case MVT::i8: + if (NumElements == 1) return MVT::v1i8; if (NumElements == 2) return MVT::v2i8; if (NumElements == 4) return MVT::v4i8; if (NumElements == 8) return MVT::v8i8; @@ -519,14 +542,18 @@ namespace llvm { break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; + if (NumElements == 4) return MVT::v4f16; + if (NumElements == 8) return MVT::v8f16; break; case MVT::f32: + if (NumElements == 1) return MVT::v1f32; if (NumElements == 2) return MVT::v2f32; if (NumElements == 4) return MVT::v4f32; if (NumElements == 8) return MVT::v8f32; if (NumElements == 16) return MVT::v16f32; break; case MVT::f64: + if (NumElements == 1) return MVT::v1f64; if (NumElements == 2) return MVT::v2f64; if (NumElements == 4) return MVT::v4f64; if (NumElements == 8) return MVT::v8f64; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index da269859491ba..b5fa0e8c6a231 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -26,7 +26,7 @@ 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 f16 : ValueType<16 , 7>; // 32-bit floating point value +def f16 : ValueType<16 , 7>; // 16-bit floating point value def f32 : ValueType<32 , 8>; // 32-bit floating point value def f64 : ValueType<64 , 9>; // 64-bit floating point value def f80 : ValueType<80 , 10>; // 80-bit floating point value @@ -39,43 +39,48 @@ def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value def v16i1 : ValueType<16, 16>; // 16 x i1 vector value def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value -def v2i8 : ValueType<16 , 19>; // 2 x i8 vector value -def v4i8 : ValueType<32 , 20>; // 4 x i8 vector value -def v8i8 : ValueType<64 , 21>; // 8 x i8 vector value -def v16i8 : ValueType<128, 22>; // 16 x i8 vector value -def v32i8 : ValueType<256, 23>; // 32 x i8 vector value -def v64i8 : ValueType<512, 24>; // 64 x i8 vector value -def v1i16 : ValueType<16 , 25>; // 1 x i16 vector value -def v2i16 : ValueType<32 , 26>; // 2 x i16 vector value -def v4i16 : ValueType<64 , 27>; // 4 x i16 vector value -def v8i16 : ValueType<128, 28>; // 8 x i16 vector value -def v16i16 : ValueType<256, 29>; // 16 x i16 vector value -def v32i16 : ValueType<512, 30>; // 32 x i16 vector value -def v1i32 : ValueType<32 , 31>; // 1 x i32 vector value -def v2i32 : ValueType<64 , 32>; // 2 x i32 vector value -def v4i32 : ValueType<128, 33>; // 4 x i32 vector value -def v8i32 : ValueType<256, 34>; // 8 x i32 vector value -def v16i32 : ValueType<512, 35>; // 16 x i32 vector value -def v1i64 : ValueType<64 , 36>; // 1 x i64 vector value -def v2i64 : ValueType<128, 37>; // 2 x i64 vector value -def v4i64 : ValueType<256, 38>; // 4 x i64 vector value -def v8i64 : ValueType<512, 39>; // 8 x i64 vector value -def v16i64 : ValueType<1024,40>; // 16 x i64 vector value +def v1i8 : ValueType<16, 19>; // 1 x i8 vector value +def v2i8 : ValueType<16 , 20>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 21>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 22>; // 8 x i8 vector value +def v16i8 : ValueType<128, 23>; // 16 x i8 vector value +def v32i8 : ValueType<256, 24>; // 32 x i8 vector value +def v64i8 : ValueType<512, 25>; // 64 x i8 vector value +def v1i16 : ValueType<16 , 26>; // 1 x i16 vector value +def v2i16 : ValueType<32 , 27>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 28>; // 4 x i16 vector value +def v8i16 : ValueType<128, 29>; // 8 x i16 vector value +def v16i16 : ValueType<256, 30>; // 16 x i16 vector value +def v32i16 : ValueType<512, 31>; // 32 x i16 vector value +def v1i32 : ValueType<32 , 32>; // 1 x i32 vector value +def v2i32 : ValueType<64 , 33>; // 2 x i32 vector value +def v4i32 : ValueType<128, 34>; // 4 x i32 vector value +def v8i32 : ValueType<256, 35>; // 8 x i32 vector value +def v16i32 : ValueType<512, 36>; // 16 x i32 vector value +def v1i64 : ValueType<64 , 37>; // 1 x i64 vector value +def v2i64 : ValueType<128, 38>; // 2 x i64 vector value +def v4i64 : ValueType<256, 39>; // 4 x i64 vector value +def v8i64 : ValueType<512, 40>; // 8 x i64 vector value +def v16i64 : ValueType<1024,41>; // 16 x i64 vector value -def v2f16 : ValueType<32 , 41>; // 2 x f16 vector value -def v2f32 : ValueType<64 , 42>; // 2 x f32 vector value -def v4f32 : ValueType<128, 43>; // 4 x f32 vector value -def v8f32 : ValueType<256, 44>; // 8 x f32 vector value -def v16f32 : ValueType<512, 45>; // 16 x f32 vector value -def v2f64 : ValueType<128, 46>; // 2 x f64 vector value -def v4f64 : ValueType<256, 47>; // 4 x f64 vector value -def v8f64 : ValueType<512, 48>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value +def v8f16 : ValueType<128, 44>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value +def v4f32 : ValueType<128, 47>; // 4 x f32 vector value +def v8f32 : ValueType<256, 48>; // 8 x f32 vector value +def v16f32 : ValueType<512, 49>; // 16 x f32 vector value +def v1f64 : ValueType<64, 50>; // 1 x f64 vector value +def v2f64 : ValueType<128, 51>; // 2 x f64 vector value +def v4f64 : ValueType<256, 52>; // 4 x f64 vector value +def v8f64 : ValueType<512, 53>; // 8 x f64 vector value -def x86mmx : ValueType<64 , 49>; // X86 MMX value -def FlagVT : ValueType<0 , 50>; // Pre-RA sched glue -def isVoid : ValueType<0 , 51>; // Produces no value -def untyped: ValueType<8 , 52>; // Produces an untyped value +def x86mmx : ValueType<64 , 54>; // X86 MMX value +def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue +def isVoid : ValueType<0 , 56>; // Produces no value +def untyped: ValueType<8 , 57>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 32d192e45523c..5c72ad8a99c21 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -21,6 +21,9 @@ /* Define if you want backtraces on crash */ #cmakedefine ENABLE_BACKTRACES +/* Define to enable crash overrides */ +#cmakedefine ENABLE_CRASH_OVERRIDES + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -33,27 +36,6 @@ /* Define to 1 if you have the `arc4random' function. */ #cmakedefine HAVE_ARC4RANDOM -/* 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. */ #cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE} @@ -78,9 +60,6 @@ /* can use __crashreporter_info__ */ #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 @@ -92,9 +71,6 @@ /* 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} @@ -104,9 +80,6 @@ /* 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} @@ -119,9 +92,6 @@ /* 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} @@ -159,17 +129,23 @@ #cmakedefine HAVE_LOG10 ${HAVE_LOG10} /* Define to 1 if you have the `exp' function. */ -#cmakedefine HAVE_EXP ${HAVE_LOG} +#cmakedefine HAVE_EXP ${HAVE_EXP} /* Define to 1 if you have the `exp2' function. */ -#cmakedefine HAVE_EXP2 ${HAVE_LOG2} +#cmakedefine HAVE_EXP2 ${HAVE_EXP2} /* Define to 1 if you have the `exp10' function. */ -#cmakedefine HAVE_EXP10 ${HAVE_LOG10} +#cmakedefine HAVE_EXP10 ${HAVE_EXP10} /* Define to 1 if you have the `fmodf' function. */ #cmakedefine HAVE_FMODF ${HAVE_FMODF} +/* Define to 1 if you have the `futimes' function. */ +#cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES} + +/* Define to 1 if you have the `futimens' function */ +#cmakedefine HAVE_FUTIMENS ${HAVE_FUTIMENS} + /* Define to 1 if you have the `getcwd' function. */ #cmakedefine HAVE_GETCWD ${HAVE_GETCWD} @@ -191,9 +167,6 @@ /* 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} @@ -230,6 +203,9 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #cmakedefine HAVE_LIBPTHREAD ${HAVE_LIBPTHREAD} +/* Define to 1 if you have the `shell32' library (-lshell32). */ +#cmakedefine HAVE_LIBSHELL32 ${HAVE_LIBSHELL32} + /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 @@ -239,12 +215,9 @@ /* 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 if you can use -rdynamic. */ #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 @@ -270,15 +243,6 @@ /* 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} @@ -344,10 +308,7 @@ #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} +#cmakedefine HAVE_REALPATH ${HAVE_REALPATH} /* Define to 1 if you have the `rintf' function. */ #undef HAVE_RINTF @@ -367,9 +328,6 @@ /* 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} @@ -388,24 +346,12 @@ /* 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} @@ -415,15 +361,6 @@ /* 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} @@ -440,9 +377,6 @@ */ #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} @@ -474,6 +408,9 @@ /* Define to 1 if you have that is POSIX.1 compatible. */ #cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} +/* Define if the setupterm() function is supported this platform. */ +#cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO} + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} @@ -495,14 +432,11 @@ /* 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} +#cmakedefine HAVE_XDOT ${HAVE_XDOT} /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} @@ -597,9 +531,6 @@ /* 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}" @@ -654,8 +585,8 @@ /* 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}" +/* Define to path to xdot.py program if found or 'echo xdot' otherwise */ +#cmakedefine LLVM_PATH_XDOT "${LLVM_PATH_XDOT}" /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" @@ -679,10 +610,6 @@ */ #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}" @@ -735,9 +662,6 @@ /* 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 diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 950e66f27503f..dcec8f8cd1ea5 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -3,6 +3,9 @@ #ifndef CONFIG_H #define CONFIG_H +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + /* Bug report URL. */ #undef BUG_REPORT_URL @@ -21,6 +24,9 @@ /* Define if you want backtraces on crash */ #undef ENABLE_BACKTRACES +/* Define to enable crash handling overrides */ +#undef ENABLE_CRASH_OVERRIDES + /* Define if position independent code is enabled */ #undef ENABLE_PIC @@ -51,15 +57,9 @@ /* 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 @@ -75,9 +75,6 @@ /* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO -/* Define to 1 if you have the header file. */ -#undef HAVE_CTYPE_H - /* Define to 1 if you have the header file. */ #undef HAVE_CXXABI_H @@ -100,9 +97,6 @@ /* 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 @@ -112,9 +106,6 @@ /* 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 @@ -166,6 +157,12 @@ /* Define to 1 if you have the `fmodf' function. */ #undef HAVE_FMODF +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD @@ -187,9 +184,6 @@ /* 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 @@ -226,16 +220,16 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD +/* Define to 1 if you have the `shell32' library (-lshell32). */ +#undef HAVE_LIBSHELL32 + /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define if you can use -Wl,-export-dynamic. */ +/* Define if you can use -rdynamic. */ #undef HAVE_LINK_EXPORT_DYNAMIC /* Define to 1 if you have the header file. */ @@ -275,12 +269,6 @@ /* 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 @@ -351,9 +339,6 @@ /* 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 @@ -393,9 +378,6 @@ /* 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 @@ -405,15 +387,6 @@ /* 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 @@ -426,9 +399,6 @@ /* 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 @@ -445,9 +415,6 @@ */ #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 @@ -479,6 +446,9 @@ /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H +/* Define if the setupterm() function is supported this platform. */ +#undef HAVE_TERMINFO + /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H @@ -500,14 +470,11 @@ /* 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 +/* Define if the xdot program is available */ +#undef HAVE_XDOT /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H @@ -602,9 +569,6 @@ /* Installation directory for .info files */ #undef LLVM_INFODIR -/* Installation directory for libraries */ -#undef LLVM_LIBDIR - /* Installation directory for man pages */ #undef LLVM_MANDIR @@ -659,8 +623,8 @@ /* 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 +/* Define to path to xdot program if found or 'echo xdot' otherwise */ +#undef LLVM_PATH_XDOT /* Installation prefix directory */ #undef LLVM_PREFIX @@ -684,10 +648,6 @@ */ #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 @@ -713,6 +673,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION @@ -737,6 +700,18 @@ /* Type of 1st arg on ELM Callback */ #undef WIN32_ELMCB_PCSTR +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index c6f2bef210dab..80616ef9508c7 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -49,9 +49,6 @@ /* 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}" diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index a5209fa9b2830..a4fae5537abed 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -49,9 +49,6 @@ /* Installation directory for .info files */ #undef LLVM_INFODIR -/* Installation directory for libraries */ -#undef LLVM_LIBDIR - /* Installation directory for man pages */ #undef LLVM_MANDIR diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index 2c0f712a9355f..bac16795f3f3d 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -17,7 +17,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; @@ -29,6 +31,7 @@ namespace llvm { class MDNode; class StringRef; class DIBasicType; + class DICompileUnit; class DICompositeType; class DIDerivedType; class DIDescriptor; @@ -37,7 +40,7 @@ namespace llvm { class DIType; class DIArray; class DIGlobalVariable; - class DIImportedModule; + class DIImportedEntity; class DINameSpace; class DIVariable; class DISubrange; @@ -53,7 +56,6 @@ namespace llvm { private: Module &M; LLVMContext & VMContext; - MDNode *TheCU; MDNode *TempEnumTypes; MDNode *TempRetainTypes; @@ -65,17 +67,24 @@ namespace llvm { Function *ValueFn; // llvm.dbg.value SmallVector AllEnumTypes; - SmallVector AllRetainTypes; + /// Use TrackingVH to collect RetainTypes, since they can be updated + /// later on. + SmallVector, 4> AllRetainTypes; SmallVector AllSubprograms; SmallVector AllGVs; SmallVector AllImportedModules; + DITemplateValueParameter + createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIType Ty, Value *Val, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; public: explicit DIBuilder(Module &M); - const MDNode *getCU() { return TheCU; } enum ComplexAddrKind { OpPlus=1, OpDeref }; /// finalize - Construct any deferred debug info descriptors. @@ -97,20 +106,24 @@ namespace llvm { /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. - void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, - StringRef Producer, bool isOptimized, - StringRef Flags, unsigned RV, - StringRef SplitName = StringRef()); + DICompileUnit createCompileUnit(unsigned Lang, StringRef File, + StringRef Dir, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RV, + StringRef SplitName = StringRef()); /// 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); + DIEnumerator createEnumerator(StringRef Name, int64_t Val); + + /// \brief Create a DWARF unspecified type. + DIBasicType createUnspecifiedType(StringRef Name); - /// createNullPtrType - Create C++0x nullptr type. - DIType createNullPtrType(StringRef Name); + /// \brief Create C++11 nullptr type. + DIBasicType createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -155,7 +168,7 @@ namespace llvm { unsigned LineNo, DIDescriptor Context); /// createFriend - Create debugging information entry for a 'friend'. - DIType createFriend(DIType Ty, DIType FriendTy); + DIDerivedType createFriend(DIType Ty, DIType FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -191,9 +204,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, DIType Ty, - unsigned Flags, llvm::Value *Val); + DIDerivedType + createStaticMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo, DIType Ty, + unsigned Flags, llvm::Value *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -212,14 +226,14 @@ namespace llvm { /// @param PropertySetterName Name of the Objective C property setter /// selector. /// @param PropertyAttributes Objective C property attributes. - DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - StringRef PropertyName = StringRef(), - StringRef PropertyGetterName = StringRef(), - StringRef PropertySetterName = StringRef(), - unsigned PropertyAttributes = 0); + DIDerivedType createObjCIVar(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty, + StringRef PropertyName = StringRef(), + StringRef PropertyGetterName = StringRef(), + StringRef PropertySetterName = StringRef(), + unsigned PropertyAttributes = 0); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -232,11 +246,11 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + DIDerivedType createObjCIVar(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty, + MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -269,13 +283,15 @@ namespace llvm { /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. + /// @param UniqueIdentifier A unique identifier for the class. DICompositeType 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); + DIType VTableHolder = DIType(), + MDNode *TemplateParms = 0, + StringRef UniqueIdentifier = StringRef()); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -287,12 +303,14 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the struct. DICompositeType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, - MDNode *VTableHolder = 0); + DIType VTableHolder = DIType(), + StringRef UniqueIdentifier = StringRef()); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -304,10 +322,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the union. DICompositeType createUnionType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0); + DIArray Elements, unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = StringRef()); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. @@ -327,15 +347,40 @@ namespace llvm { /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. - /// @param Value Constant parameter value. + /// @param Val 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); + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, + DIType Ty, Value *Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + + /// \brief Create debugging information for a template template parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Value parameter name. + /// @param Ty Parameter type. + /// @param Val The fully qualified name of the template. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, + DIType Ty, StringRef Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + + /// \brief Create debugging information for a template parameter pack. + /// @param Scope Scope in which this type is defined. + /// @param Name Value parameter name. + /// @param Ty Parameter type. + /// @param Val An array of types in the pack. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateParameterPack(DIDescriptor Scope, StringRef Name, + DIType Ty, DIArray Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. @@ -350,8 +395,8 @@ namespace llvm { /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -363,12 +408,11 @@ namespace llvm { /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + /// @param UniqueIdentifier A unique identifier for the enum. DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - DIArray Elements, - DIType UnderlyingType); + DIFile File, unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, + StringRef UniqueIdentifier = StringRef()); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -384,9 +428,12 @@ namespace llvm { DIType createObjectPointerType(DIType Ty); /// createForwardDecl - Create a temporary forward-declared type. - DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, - DIFile F, unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, uint64_t AlignInBits = 0); + DICompositeType createForwardDecl(unsigned Tag, StringRef Name, + DIDescriptor Scope, DIFile F, + unsigned Line, unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -460,7 +507,7 @@ namespace llvm { /// @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 + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, @@ -480,7 +527,7 @@ namespace llvm { /// @param LineNo Line number. /// @param Ty Variable Type /// @param Addr An array of complex address operations. - /// @param ArgNo If this variable is an arugment then this argument's + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, @@ -506,7 +553,21 @@ namespace llvm { DISubprogram createFunction(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, + DICompositeType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0, + MDNode *TParam = 0, + MDNode *Decl = 0); + + /// FIXME: this is added for dragonegg. Once we update dragonegg + /// to call resolve function, this will be removed. + DISubprogram createFunction(DIScopeRef Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, @@ -537,10 +598,10 @@ namespace llvm { DISubprogram createMethod(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, + DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, unsigned VTableIndex = 0, - MDNode *VTableHolder = 0, + DIType VTableHolder = DIType(), unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, @@ -577,8 +638,25 @@ namespace llvm { /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedModule createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, + unsigned Line, + StringRef Name = StringRef()); + + /// \brief Create a descriptor for an imported module. + /// @param Context The scope this module is imported into + /// @param NS An aliased namespace + /// @param Line Line number + DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, + unsigned Line, StringRef Name); + + /// \brief Create a descriptor for an imported function. + /// @param Context The scope this module is imported into + /// @param Decl The declaration (or definition) of a function, type, or + /// variable + /// @param Line Line number + DIImportedEntity createImportedDeclaration(DIScope Context, + DIDescriptor Decl, + unsigned Line); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index f9b58f4770a9b..768cf4ea10f22 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -17,769 +17,834 @@ #ifndef LLVM_DEBUGINFO_H #define LLVM_DEBUGINFO_H +#include "llvm/Support/Casting.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Metadata.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 DILexicalBlockFile; - class DIVariable; - class DIType; - class DIObjCProperty; - - /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. - /// This should not be stored in a container, because the underlying 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, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12 - }; - protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(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; - void replaceFunctionField(unsigned Elt, Function *F); - - 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 DILexicalBlockFile F); - explicit DIDescriptor(const DILexicalBlock F); - explicit DIDescriptor(const DIVariable F); - explicit DIDescriptor(const DIType F); - - bool Verify() const; - - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator ->() const { return const_cast(DbgNode); } - - unsigned getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; - } - - 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 isLexicalBlockFile() 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; - bool isObjCProperty() const; - bool isImportedModule() const; - - /// print - print descriptor. - void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. - void dump() const; +class BasicBlock; +class Constant; +class Function; +class GlobalVariable; +class Module; +class Type; +class Value; +class DbgDeclareInst; +class DbgValueInst; +class Instruction; +class MDNode; +class MDString; +class NamedMDNode; +class LLVMContext; +class raw_ostream; + +class DIFile; +class DISubprogram; +class DILexicalBlock; +class DILexicalBlockFile; +class DIVariable; +class DIType; +class DIScope; +class DIObjCProperty; + +/// Maps from type identifier to the actual MDNode. +typedef DenseMap DITypeIdentifierMap; + +/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. +/// This should not be stored in a container, because the underlying MDNode +/// may change in certain situations. +class DIDescriptor { + // Befriends DIRef so DIRef can befriend the protected member + // function: getFieldAs. + template friend class DIRef; + +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, + FlagObjcClassComplete = 1 << 9, + FlagObjectPointer = 1 << 10, + FlagVector = 1 << 11, + FlagStaticMember = 1 << 12, + FlagIndirectVariable = 1 << 13 }; - /// DISubrange - This is used to represent ranges, for array bounds. - class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} - - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } - bool Verify() const; - }; - - /// 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 { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} - - StringRef getFilename() const; - StringRef getDirectory() const; - }; - - /// DIFile - This is a wrapper for a file. - class DIFile : public DIScope { - friend class DIDescriptor; - public: - explicit DIFile(const MDNode *N = 0) : DIScope(N) { - if (DbgNode && !isFile()) - DbgNode = 0; - } - MDNode *getFileNode() const; - bool Verify() const; - }; - - /// DICompileUnit - A wrapper for a compile unit. - class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} - - unsigned getLanguage() const { return getUnsignedField(2); } - StringRef getProducer() const { return getStringField(3); } - - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedModules() const; - - StringRef getSplitDebugFilename() const { return getStringField(12); } - - /// Verify - Verify that a compile unit is well formed. - bool Verify() const; - }; - - /// 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} - - StringRef getName() const { return getStringField(1); } - uint64_t getEnumValue() const { return getUInt64Field(2); } - bool Verify() const; - }; - - /// 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 { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - // 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; - explicit DIType(const MDNode *N); - explicit DIType() {} - - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(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 isObjectPointer() const { - return (getFlags() & FlagObjectPointer) != 0; - } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { - return (getFlags() & FlagVector) != 0; - } - bool isStaticMember() const { - return (getFlags() & FlagStaticMember) != 0; - } - bool isValid() const { - return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); - } - - /// isUnsignedDIType - Return true if type encoding is unsigned. - bool isUnsignedDIType(); - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(DIDescriptor &D); - void replaceAllUsesWith(MDNode *D); - }; - - /// 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; - }; - - /// DIDerivedType - A simple derived type, like a const qualified type, - /// a typedef, a pointer or reference, et cetera. Or, a data member of - /// a class/struct/union. - class DIDerivedType : public DIType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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; - - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. - MDNode *getObjCProperty() const; - - DIType getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs(10); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); - } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// DICompositeType - This descriptor holds a type that can refer to multiple - /// other types, like a function or struct. - /// DICompositeType is derived from DIDerivedType because some - /// composite types (such as enums) can be derived from basic types - // FIXME: Make this derive from DIType directly & just store the - // base type in a single DIType field. - class DICompositeType : public DIDerivedType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompositeType(const MDNode *N = 0) - : DIDerivedType(N, true, true) { - if (N && !isCompositeType()) - DbgNode = 0; - } - - DIArray getTypeArray() const { return getFieldAs(10); } - void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - unsigned getRunTimeLang() const { return getUnsignedField(11); } - DICompositeType getContainingType() const { - return getFieldAs(12); - } - void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs(13); } - - /// Verify - Verify that a composite type descriptor is well formed. - bool Verify() 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); } - bool Verify() const; - }; - - /// 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); } - bool Verify() const; - }; - - /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). - class DISubprogram : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DICompositeType getType() const { return getFieldAs(7); } - - /// getReturnTypeName - Subprogram return types are encoded either as - /// DIType or as DICompositeType. - StringRef getReturnTypeName() const { - DICompositeType DCT(getFieldAs(7)); - if (DCT.Verify()) { - DIArray A = DCT.getTypeArray(); - DIType T(A.getElement(0)); - return T.getName(); - } - DIType T(getFieldAs(7)); - 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(8); } - unsigned isDefinition() const { return getUnsignedField(9); } - - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } - - DICompositeType getContainingType() const { - return getFieldAs(12); - } - - unsigned getFlags() const { - return getUnsignedField(13); - } - - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { - return (getUnsignedField(13) & FlagPrivate) != 0; - } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getUnsignedField(13) & FlagProtected) != 0; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { - return (getUnsignedField(13) & FlagExplicit) != 0; - } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } - - unsigned isOptimized() const; - - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } - - /// Verify - Verify that a subprogram descriptor is well formed. - bool Verify() const; - - /// describes - Return true if this subprogram provides debugging - /// information for the function F. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs(16); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs(17); - } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; - }; - - /// DIGlobalVariable - This is a wrapper for a global variable. - class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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); } - StringRef getFilename() const { - return getFieldAs(6).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs(6).getDirectory(); - - } - - 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); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs(12); - } - - /// Verify - Verify that a global variable descriptor is well formed. - bool Verify() const; - }; - - /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, - /// global etc). - class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIVariable(const MDNode *N = 0) - : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs(3); } - 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 { - return (getUnsignedField(6) & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; - } - - /// getInlinedAt - If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - /// 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+8); - } - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). - bool isBlockByrefVariable() const { - return getType().isBlockByrefStruct(); - } - - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. - bool isInlinedFnArgument(const Function *CurFn); - - void printExtendedName(raw_ostream &OS) 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(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DILexicalBlockFile - This is a wrapper for a lexical block with - /// a filename change. - class DILexicalBlockFile : public DIScope { - public: - explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs(2); } - bool Verify() const; - }; - - /// DINameSpace - A wrapper for a C++ style name space. - class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - 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; - }; - - class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) { } - - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - - StringRef getObjCPropertyGetterName() const { - return getStringField(4); - } - StringRef getObjCPropertySetterName() const { - return getStringField(5); - } - bool isReadOnlyObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - DIType getType() const { return getFieldAs(7); } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// \brief An imported module (C++ using directive or similar). - class DIImportedModule : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIImportedModule(const MDNode *N) : DIDescriptor(N) { } - DIScope getContext() const { return getFieldAs(1); } - DINameSpace getNameSpace() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - 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); - - /// isSubprogramContext - Return true if Context is either a subprogram - /// or another context nested inside a subprogram. - bool isSubprogramContext(const MDNode *Context); - - /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable - /// to hold function specific information. - NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); - - /// getFnSpecificMDNode - Return a NameMDNode, if available, that is - /// suitable to hold function specific information. - NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); - - /// createInlinedVariable - Create a new inlined variable based on current - /// variable. - /// @param DV Current Variable. - /// @param InlinedScope Location at current variable is inlined. - DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); - - /// cleanseInlinedVariable - Remove inlined scope from the variable. - DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); - - class DebugInfoFinder { - public: - /// processModule - Process entire module and collect debug info - /// anchors. - void processModule(const 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(const 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 subprogram 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; - }; +protected: + const MDNode *DbgNode; + + StringRef getStringField(unsigned Elt) const; + unsigned getUnsignedField(unsigned Elt) const { + return (unsigned)getUInt64Field(Elt); + } + uint64_t getUInt64Field(unsigned Elt) const; + int64_t getInt64Field(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; + void replaceFunctionField(unsigned Elt, Function *F); + +public: + explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} + + bool Verify() const; + + operator MDNode *() const { return const_cast(DbgNode); } + MDNode *operator->() const { return const_cast(DbgNode); } + + // An explicit operator bool so that we can do testing of DI values + // easily. + // FIXME: This operator bool isn't actually protecting anything at the + // moment due to the conversion operator above making DIDescriptor nodes + // implicitly convertable to bool. + LLVM_EXPLICIT operator bool() const { return DbgNode != 0; } + + bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } + bool operator!=(DIDescriptor Other) const { return !operator==(Other); } + + uint16_t getTag() const { + return getUnsignedField(0) & ~LLVMDebugVersionMask; + } + + 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 isLexicalBlockFile() const; + bool isLexicalBlock() const; + bool isSubrange() const; + bool isEnumerator() const; + bool isType() const; + bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; + bool isObjCProperty() const; + bool isImportedEntity() const; + + /// print - print descriptor. + void print(raw_ostream &OS) const; + + /// dump - print descriptor to dbgs() with a newline. + void dump() const; +}; + +/// DISubrange - This is used to represent ranges, for array bounds. +class DISubrange : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} + + int64_t getLo() const { return getInt64Field(1); } + int64_t getCount() const { return getInt64Field(2); } + bool Verify() const; +}; + +/// 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); + } +}; + +/// 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 { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} + + StringRef getName() const { return getStringField(1); } + int64_t getEnumValue() const { return getInt64Field(2); } + bool Verify() const; +}; + +template class DIRef; +typedef DIRef DIScopeRef; +typedef DIRef DITypeRef; + +/// DIScope - A base class for various scopes. +class DIScope : public DIDescriptor { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIScope(const MDNode *N = 0) : DIDescriptor(N) {} + + /// Gets the parent scope for this scope node or returns a + /// default constructed scope. + DIScopeRef getContext() const; + /// If the scope node has a name, return that, else return an empty string. + StringRef getName() const; + StringRef getFilename() const; + StringRef getDirectory() const; + + /// Generate a reference to this DIScope. Uses the type identifier instead + /// of the actual MDNode if possible, to help type uniquing. + DIScopeRef getRef() const; +}; + +/// Represents reference to a DIDescriptor, abstracts over direct and +/// identifier-based metadata references. +template class DIRef { + template + friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; + friend DIScopeRef DIScope::getContext() const; + friend DIScopeRef DIScope::getRef() const; + + /// Val can be either a MDNode or a MDString, in the latter, + /// MDString specifies the type identifier. + const Value *Val; + explicit DIRef(const Value *V); + +public: + T resolve(const DITypeIdentifierMap &Map) const; + StringRef getName() const; + operator Value *() const { return const_cast(Val); } +}; + +template +T DIRef::resolve(const DITypeIdentifierMap &Map) const { + if (!Val) + return T(); + + if (const MDNode *MD = dyn_cast(Val)) + return T(MD); + + const MDString *MS = cast(Val); + // Find the corresponding MDNode. + DITypeIdentifierMap::const_iterator Iter = Map.find(MS); + assert(Iter != Map.end() && "Identifier not in the type map?"); + assert(DIDescriptor(Iter->second).isType() && + "MDNode in DITypeIdentifierMap should be a DIType."); + return T(Iter->second); +} + +template StringRef DIRef::getName() const { + if (!Val) + return StringRef(); + + if (const MDNode *MD = dyn_cast(Val)) + return T(MD).getName(); + + const MDString *MS = cast(Val); + return MS->getString(); +} + +/// Specialize getFieldAs to handle fields that are references to DIScopes. +template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// Specialize DIRef constructor for DIScopeRef. +template <> DIRef::DIRef(const Value *V); + +/// Specialize getFieldAs to handle fields that are references to DITypes. +template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// Specialize DIRef constructor for DITypeRef. +template <> DIRef::DIRef(const Value *V); + +/// 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 { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIType(const MDNode *N = 0) : DIScope(N) {} + + /// Verify - Verify that a type descriptor is well formed. + bool Verify() const; + + DIScopeRef getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(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 isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } + bool isObjcClassComplete() const { + return (getFlags() & FlagObjcClassComplete) != 0; + } + bool isVector() const { return (getFlags() & FlagVector) != 0; } + bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } + bool isValid() const { return DbgNode && isType(); } + + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. + void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); +}; + +/// 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; +}; + +/// DIDerivedType - A simple derived type, like a const qualified type, +/// a typedef, a pointer or reference, et cetera. Or, a data member of +/// a class/struct/union. +class DIDerivedType : public DIType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} + + DITypeRef getTypeDerivedFrom() const { return getFieldAs(9); } + + /// getObjCProperty - Return property node, if this ivar is + /// associated with one. + MDNode *getObjCProperty() const; + + DITypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return getFieldAs(10); + } + + Constant *getConstant() const { + assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); + return getConstantField(10); + } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// DICompositeType - This descriptor holds a type that can refer to multiple +/// other types, like a function or struct. +/// DICompositeType is derived from DIDerivedType because some +/// composite types (such as enums) can be derived from basic types +// FIXME: Make this derive from DIType directly & just store the +// base type in a single DIType field. +class DICompositeType : public DIDerivedType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} + + DIArray getTypeArray() const { return getFieldAs(10); } + void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); + void addMember(DIDescriptor D); + unsigned getRunTimeLang() const { return getUnsignedField(11); } + DITypeRef getContainingType() const { return getFieldAs(12); } + void setContainingType(DICompositeType ContainingType); + DIArray getTemplateParams() const { return getFieldAs(13); } + MDString *getIdentifier() const; + + /// Verify - Verify that a composite type descriptor is well formed. + bool Verify() const; +}; + +/// DIFile - This is a wrapper for a file. +class DIFile : public DIScope { + friend class DIDescriptor; + +public: + explicit DIFile(const MDNode *N = 0) : DIScope(N) {} + MDNode *getFileNode() const; + bool Verify() const; +}; + +/// DICompileUnit - A wrapper for a compile unit. +class DICompileUnit : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} + + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getProducer() const { return getStringField(3); } + + bool isOptimized() const { return getUnsignedField(4) != 0; } + StringRef getFlags() const { return getStringField(5); } + unsigned getRunTimeVersion() const { return getUnsignedField(6); } + + DIArray getEnumTypes() const; + DIArray getRetainedTypes() const; + DIArray getSubprograms() const; + DIArray getGlobalVariables() const; + DIArray getImportedEntities() const; + + StringRef getSplitDebugFilename() const { return getStringField(12); } + + /// Verify - Verify that a compile unit is well formed. + bool Verify() const; +}; + +/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +class DISubprogram : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} + + DIScopeRef getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + unsigned getLineNumber() const { return getUnsignedField(6); } + DICompositeType getType() const { return getFieldAs(7); } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(8); } + unsigned isDefinition() const { return getUnsignedField(9); } + + unsigned getVirtuality() const { return getUnsignedField(10); } + unsigned getVirtualIndex() const { return getUnsignedField(11); } + + DITypeRef getContainingType() const { return getFieldAs(12); } + + unsigned getFlags() const { return getUnsignedField(13); } + + unsigned isArtificial() const { + return (getUnsignedField(13) & FlagArtificial) != 0; + } + /// isPrivate - Return true if this subprogram has "private" + /// access specifier. + bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; } + /// isProtected - Return true if this subprogram has "protected" + /// access specifier. + bool isProtected() const { + return (getUnsignedField(13) & FlagProtected) != 0; + } + /// isExplicit - Return true if this subprogram is marked as explicit. + bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } + /// isPrototyped - Return true if this subprogram is prototyped. + bool isPrototyped() const { + return (getUnsignedField(13) & FlagPrototyped) != 0; + } + + unsigned isOptimized() const; + + /// Verify - Verify that a subprogram descriptor is well formed. + bool Verify() const; + + /// describes - Return true if this subprogram provides debugging + /// information for the function F. + bool describes(const Function *F); + + Function *getFunction() const { return getFunctionField(15); } + void replaceFunction(Function *F) { replaceFunctionField(15, F); } + DIArray getTemplateParams() const { return getFieldAs(16); } + DISubprogram getFunctionDeclaration() const { + return getFieldAs(17); + } + MDNode *getVariablesNodes() const; + DIArray getVariables() const; + + /// getScopeLineNumber - Get the beginning of the scope of the + /// function, not necessarily where the name of the program + /// starts. + unsigned getScopeLineNumber() const { return getUnsignedField(19); } +}; + +/// 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(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + unsigned getColumnNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DILexicalBlockFile - This is a wrapper for a lexical block with +/// a filename change. +class DILexicalBlockFile : public DIScope { +public: + explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { + if (getScope().isSubprogram()) + return getScope(); + return getScope().getContext(); + } + unsigned getLineNumber() const { return getScope().getLineNumber(); } + unsigned getColumnNumber() const { return getScope().getColumnNumber(); } + DILexicalBlock getScope() const { return getFieldAs(2); } + bool Verify() const; +}; + +/// DINameSpace - A wrapper for a C++ style name space. +class DINameSpace : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DITemplateTypeParameter - This is a wrapper for template type parameter. +class DITemplateTypeParameter : public DIDescriptor { +public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef 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); } + bool Verify() const; +}; + +/// DITemplateValueParameter - This is a wrapper for template value parameter. +class DITemplateValueParameter : public DIDescriptor { +public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef getType() const { return getFieldAs(3); } + Value *getValue() const; + 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); } + bool Verify() const; +}; + +/// DIGlobalVariable - This is a wrapper for a global variable. +class DIGlobalVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +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); } + StringRef getFilename() const { return getFieldAs(6).getFilename(); } + StringRef getDirectory() const { + return getFieldAs(6).getDirectory(); + } + + 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); } + DIDerivedType getStaticDataMemberDeclaration() const { + return getFieldAs(12); + } + + /// Verify - Verify that a global variable descriptor is well formed. + bool Verify() const; +}; + +/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, +/// global etc). +class DIVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DIFile getFile() const { return getFieldAs(3); } + 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 { + return (getUnsignedField(6) & FlagArtificial) != 0; + } + + bool isObjectPointer() const { + return (getUnsignedField(6) & FlagObjectPointer) != 0; + } + + /// \brief Return true if this variable is represented as a pointer. + bool isIndirect() const { + return (getUnsignedField(6) & FlagIndirectVariable) != 0; + } + + /// getInlinedAt - If this variable is inlined then return inline location. + MDNode *getInlinedAt() const; + + /// 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 + 8); + } + + /// isBlockByrefVariable - Return true if the variable was declared as + /// a "__block" variable (Apple Blocks). + bool isBlockByrefVariable() const { return getType().isBlockByrefStruct(); } + + /// isInlinedFnArgument - Return true if this variable provides debugging + /// information for an inlined function arguments. + bool isInlinedFnArgument(const Function *CurFn); + + void printExtendedName(raw_ostream &OS) 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; +}; + +class DIObjCProperty : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} + + StringRef getObjCPropertyName() const { return getStringField(1); } + DIFile getFile() const { return getFieldAs(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + + StringRef getObjCPropertyGetterName() const { return getStringField(4); } + StringRef getObjCPropertySetterName() const { return getStringField(5); } + bool isReadOnlyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + } + bool isReadWriteObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + } + bool isAssignObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + } + bool isRetainObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + } + bool isCopyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + } + bool isNonAtomicObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + } + + DIType getType() const { return getFieldAs(7); } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// \brief An imported module (C++ using directive or similar). +class DIImportedEntity : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} + DIScope getContext() const { return getFieldAs(1); } + DIDescriptor getEntity() const { return getFieldAs(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getName() const { return getStringField(4); } + 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, DISubprogram SP); + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); + +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext); + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); + +/// Construct DITypeIdentifierMap by going through retained types of each CU. +DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); + +/// Strip debug info in the module if it exists. +/// To do this, we remove all calls to the debugger intrinsics and any named +/// metadata for debugging. We also remove debug locations for instructions. +/// Return true if module is modified. +bool StripDebugInfo(Module &M); + +/// Return Debug Info Metadata Version by checking module flags. +unsigned getDebugMetadataVersionFromModule(const Module &M); + +/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To +/// list debug info MDNodes used by an instruction, DebugInfoFinder uses +/// processDeclare, processValue and processLocation to handle DbgDeclareInst, +/// DbgValueInst and DbgLoc attached to instructions. processModule will go +/// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes +/// used by the CUs. +class DebugInfoFinder { +public: + DebugInfoFinder() : TypeMapInitialized(false) {} + + /// processModule - Process entire module and collect debug info + /// anchors. + void processModule(const Module &M); + + /// processDeclare - Process DbgDeclareInst. + void processDeclare(const Module &M, const DbgDeclareInst *DDI); + /// Process DbgValueInst. + void processValue(const Module &M, const DbgValueInst *DVI); + /// processLocation - Process DILocation. + void processLocation(const Module &M, DILocation Loc); + + /// Clear all lists. + void reset(); + +private: + /// Initialize TypeIdentifierMap. + void InitializeTypeMap(const Module &M); + + /// processType - Process DIType. + void processType(DIType DT); + + /// processLexicalBlock - Process DILexicalBlock. + void processLexicalBlock(DILexicalBlock LB); + + /// processSubprogram - Process DISubprogram. + void processSubprogram(DISubprogram SP); + + void processScope(DIScope Scope); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprogram into SPs. + bool addSubprogram(DISubprogram SP); + + /// addType - Add type into Tys. + bool addType(DIType DT); + + bool addScope(DIScope Scope); + +public: + typedef SmallVectorImpl::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(); } + iterator scope_begin() const { return Scopes.begin(); } + iterator scope_end() const { return Scopes.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(); } + unsigned scope_count() const { return Scopes.size(); } + +private: + SmallVector CUs; // Compile Units + SmallVector SPs; // Subprograms + SmallVector GVs; // Global Variables; + SmallVector TYs; // Types + SmallVector Scopes; // Scopes + SmallPtrSet NodesSeen; + DITypeIdentifierMap TypeIdentifierMap; + /// Specify if TypeIdentifierMap is initialized. + bool TypeMapInitialized; +}; } // end namespace llvm #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 8fcd9e0b8246b..a1a4642103d88 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -37,11 +38,10 @@ public: DILineInfo() : FileName(""), FunctionName(""), Line(0), Column(0) {} - DILineInfo(const SmallString<16> &fileName, - const SmallString<16> &functionName, - uint32_t line, uint32_t column) - : FileName(fileName), FunctionName(functionName), - Line(line), Column(column) {} + DILineInfo(StringRef fileName, StringRef functionName, uint32_t line, + uint32_t column) + : FileName(fileName), FunctionName(functionName), Line(line), + Column(column) {} const char *getFileName() { return FileName.c_str(); } const char *getFunctionName() { return FunctionName.c_str(); } @@ -104,9 +104,14 @@ enum DIDumpType { DIDT_Frames, DIDT_Info, DIDT_InfoDwo, + DIDT_Types, DIDT_Line, + DIDT_Loc, DIDT_Ranges, DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, DIDT_Str, DIDT_StrDwo, DIDT_StrOffsetsDwo @@ -121,6 +126,12 @@ typedef DenseMap > RelocAddrMap; class DIContext { public: + enum DIContextKind { + CK_DWARF + }; + DIContextKind getKind() const { return Kind; } + + DIContext(DIContextKind K) : Kind(K) {} virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. @@ -134,6 +145,8 @@ public: uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; }; } diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index eaaccfb4f33b3..533d2593b18b1 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -10,15 +10,31 @@ #ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H #define LLVM_DEBUGINFO_DWARFFORMVALUE_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/DataExtractor.h" namespace llvm { -class DWARFCompileUnit; +class DWARFUnit; class raw_ostream; class DWARFFormValue { public: + enum FormClass { + FC_Unknown, + FC_Address, + FC_Block, + FC_Constant, + FC_String, + FC_Flag, + FC_Reference, + FC_Indirect, + FC_SectionOffset, + FC_Exprloc + }; + +private: struct ValueType { ValueType() : data(NULL) { uval = 0; @@ -32,49 +48,36 @@ public: const uint8_t* data; }; - enum { - eValueTypeInvalid = 0, - eValueTypeUnsigned, - eValueTypeSigned, - eValueTypeCStr, - eValueTypeBlock - }; - -private: uint16_t Form; // Form for this value. ValueType Value; // Contains all data for the form. public: - DWARFFormValue(uint16_t form = 0) : Form(form) {} + DWARFFormValue(uint16_t Form = 0) : Form(Form) {} uint16_t getForm() const { return Form; } - const ValueType& value() const { return Value; } - void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const; + bool isFormClass(FormClass FC) const; + + void dump(raw_ostream &OS, const DWARFUnit *U) const; bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu); + const DWARFUnit *u); bool isInlinedCStr() const { return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr; } - const uint8_t *BlockData() const; - uint64_t getReference(const DWARFCompileUnit* cu) const; - /// Resolve any compile unit specific references so that we don't need - /// the compile unit at a later time in order to work with the form - /// value. - bool resolveCompileUnitReferences(const DWARFCompileUnit* cu); - uint64_t getUnsigned() const { return Value.uval; } - int64_t getSigned() const { return Value.sval; } - const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; - const char *getIndirectCString(const DataExtractor *, - const DataExtractor *) const; - uint64_t getIndirectAddress(const DataExtractor *, - const DWARFCompileUnit *) const; + /// getAsFoo functions below return the extracted value as Foo if only + /// DWARFFormValue has form class is suitable for representing Foo. + Optional getAsReference(const DWARFUnit *U) const; + Optional getAsUnsignedConstant() const; + Optional getAsCString(const DWARFUnit *U) const; + Optional getAsAddress(const DWARFUnit *U) const; + Optional getAsSectionOffset() const; + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu) const; + const DWARFUnit *u) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFCompileUnit *cu); - static bool isBlockForm(uint16_t form); - static bool isDataForm(uint16_t form); - static const uint8_t *getFixedFormSizes(uint8_t AddrSize, uint16_t Version); + uint32_t *offset_ptr, const DWARFUnit *u); + + static ArrayRef getFixedFormSizes(uint8_t AddrSize, + uint16_t Version); }; } diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index bbaebc6f906b3..233084dd50fad 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -16,7 +16,6 @@ #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #include "llvm-c/ExecutionEngine.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" @@ -34,6 +33,7 @@ namespace llvm { struct GenericValue; class Constant; +class DataLayout; class ExecutionEngine; class Function; class GlobalVariable; @@ -44,7 +44,7 @@ class MachineCodeInfo; class Module; class MutexGuard; class ObjectCache; -class DataLayout; +class RTDyldMemoryManager; class Triple; class Type; @@ -142,7 +142,7 @@ protected: static ExecutionEngine *(*MCJITCtor)( Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MCJMM, bool GVsWithCode, TargetMachine *TM); static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); @@ -152,17 +152,8 @@ protected: /// 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 + /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. sys::Mutex lock; @@ -224,7 +215,7 @@ public: /// 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); + virtual Function *FindFunctionNamed(const char *FnName); /// runFunction - Execute the specified function with the specified arguments, /// and return the result. @@ -239,6 +230,11 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// + /// This function is deprecated for the MCJIT execution engine. + /// + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// again, if possible. + /// virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) = 0; @@ -251,18 +247,38 @@ public: "EE!"); } - // finalizeObject - This method should be called after sections within an - // object have been relocated using mapSectionAddress. When this method is - // called the MCJIT execution engine will reapply relocations for a loaded - // object. This method has no effect for the legacy JIT engine or the - // interpeter. + /// generateCodeForModule - Run code generationen for the specified module and + /// load it into memory. + /// + /// When this function has completed, all code and data for the specified + /// module, and any module on which this module depends, will be generated + /// and loaded into memory, but relocations will not yet have been applied + /// and all memory will be readable and writable but not executable. + /// + /// This function is primarily useful when generating code for an external + /// target, allowing the client an opportunity to remap section addresses + /// before relocations are applied. Clients that intend to execute code + /// locally can use the getFunctionAddress call, which will generate code + /// and apply final preparations all in one step. + /// + /// This method has no effect for the legacy JIT engine or the interpeter. + virtual void generateCodeForModule(Module *M) {} + + /// finalizeObject - ensure the module is fully processed and is usable. + /// + /// It is the user-level function for completing the process of making the + /// object usable for execution. It should be called after sections within an + /// object have been relocated using mapSectionAddress. When this method is + /// called the MCJIT execution engine will reapply relocations for a loaded + /// object. This method has no effect for the legacy JIT engine or the + /// interpeter. virtual void finalizeObject() {} /// 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); + virtual void runStaticConstructorsDestructors(bool isDtors); /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a particular module. @@ -303,10 +319,16 @@ public: /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. + /// + /// This function is deprecated for the MCJIT execution engine. It doesn't + /// seem to be needed in that case, but an equivalent can be added if it is. 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. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in @@ -314,22 +336,48 @@ public: /// 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. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. 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. + /// + /// This function will not be implemented for the MCJIT execution engine. 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. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } + /// getGlobalValueAddress - Return the address of the specified global + /// value. This may involve code generation. + /// + /// This function should not be called with the JIT or interpreter engines. + virtual uint64_t getGlobalValueAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToGlobal instead. + return 0; + } + + /// getFunctionAddress - Return the address of the specified function. + /// This may involve code generation. + virtual uint64_t getFunctionAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToFunction instead. + return 0; + } + // The JIT overrides a version that actually does this. virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } @@ -362,6 +410,9 @@ public: /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((const GlobalValue *)GV); } @@ -431,41 +482,6 @@ public: 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); @@ -496,6 +512,7 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; + RTDyldMemoryManager *MCJMM; JITMemoryManager *JMM; bool AllocateGVsWithCode; TargetOptions Options; @@ -511,6 +528,7 @@ private: WhichEngine = EngineKind::Either; ErrorStr = NULL; OptLevel = CodeGenOpt::Default; + MCJMM = NULL; JMM = NULL; Options = TargetOptions(); AllocateGVsWithCode = false; @@ -532,12 +550,29 @@ public: WhichEngine = w; return *this; } + + /// setMCJITMemoryManager - Sets the MCJIT memory manager to use. This allows + /// clients to customize their memory allocation policies for the MCJIT. This + /// is only appropriate for the MCJIT; setting this and configuring the builder + /// to create anything other than MCJIT will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. Using this option nullifies + /// the setJITMemoryManager() option. + EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { + MCJMM = mcjmm; + JMM = NULL; + 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. + /// setJITMemoryManager - Sets the JIT memory manager to use. This allows + /// clients to customize their memory allocation policies. This is only + /// appropriate for either JIT or MCJIT; setting this and configuring the + /// builder to create an interpreter will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. This option overrides + /// setMCJITMemoryManager() as well. EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + MCJMM = NULL; JMM = jmm; return *this; } diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 714a98055a42a..b22d899c9fec3 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -115,22 +115,6 @@ public: /// 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. diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index 96a48b28b8477..af2a9263ff120 100644 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -30,6 +30,7 @@ namespace llvm { /// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the /// actual memory it points to. class ObjectBuffer { + virtual void anchor(); public: ObjectBuffer() {} ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} @@ -44,6 +45,7 @@ public: const char *getBufferStart() const { return Buffer->getBufferStart(); } size_t getBufferSize() const { return Buffer->getBufferSize(); } + StringRef getBuffer() const { return Buffer->getBuffer(); } protected: // The memory contained in an ObjectBuffer @@ -55,6 +57,7 @@ protected: /// while providing a common ObjectBuffer interface for access to the /// memory once the object has been generated. class ObjectBufferStream : public ObjectBuffer { + virtual void anchor(); public: ObjectBufferStream() : OS(SV) {} virtual ~ObjectBufferStream() {} diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index 0bee86161bb7a..d1849dfc3bf65 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H -#define LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H +#ifndef LLVM_EXECUTIONENGINE_OBJECTCACHE_H +#define LLVM_EXECUTIONENGINE_OBJECTCACHE_H #include "llvm/Support/MemoryBuffer.h" @@ -20,6 +20,7 @@ class Module; /// ExecutionEngine for the purpose of avoiding compilation for Modules that /// have already been compiled and an object file is available. class ObjectCache { + virtual void anchor(); public: ObjectCache() { } @@ -30,23 +31,9 @@ public: /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns the MemoryBuffer returned by this function. - MemoryBuffer* getObjectCopy(const Module* M) { - const MemoryBuffer* Obj = getObject(M); - if (Obj) - return MemoryBuffer::getMemBufferCopy(Obj->getBuffer()); - else - return 0; - } - -protected: - /// getObject - Returns a pointer to a MemoryBuffer that contains an object - /// that corresponds with Module M, or 0 if an object is not available. - /// The pointer returned by this function is not suitable for loading because - /// the memory is read-only and owned by the ObjectCache. To retrieve an - /// owning pointer to a MemoryBuffer (which is suitable for calling - /// RuntimeDyld::loadObject() with) use getObjectCopy() instead. - virtual const MemoryBuffer* getObject(const Module* M) = 0; + /// not available. The caller owns both the MemoryBuffer returned by this + /// and the memory it references. + virtual MemoryBuffer* getObject(const Module* M) = 0; }; } diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h index 9fddca7e33c85..076f4b1146c10 100644 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -25,6 +25,7 @@ namespace llvm { class ObjectImage { ObjectImage() LLVM_DELETED_FUNCTION; ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; + virtual void anchor(); protected: OwningPtr Buffer; diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h new file mode 100644 index 0000000000000..3ad2e5022da38 --- /dev/null +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -0,0 +1,112 @@ +//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface of the runtime dynamic memory manager base class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Memory.h" +#include "llvm-c/ExecutionEngine.h" + +namespace llvm { + +class ExecutionEngine; +class ObjectImage; + +// RuntimeDyld clients often want to handle the memory management of +// what gets placed where. For JIT clients, this is the subset of +// JITMemoryManager required for dynamic loading of binaries. +// +// FIXME: As the RuntimeDyld fills out, additional routines will be needed +// for the varying types of objects to be allocated. +class RTDyldMemoryManager { + RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; +public: + RTDyldMemoryManager() {} + virtual ~RTDyldMemoryManager(); + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the JIT + /// engine, and optionally recorded by the memory manager to access a loaded + /// section. + virtual uint8_t *allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool IsReadOnly) = 0; + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual uint64_t getSymbolAddress(const std::string &Name); + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + /// + /// This function is deprecated for memory managers to be used with + /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *) {} + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS( + RTDyldMemoryManager, LLVMMCJITMemoryManagerRef) + +} // namespace llvm + +#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index c6c126c6e242e..b8324387bbe6d 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" namespace llvm { @@ -23,56 +24,6 @@ namespace llvm { class RuntimeDyldImpl; class ObjectImage; -// RuntimeDyld clients often want to handle the memory management of -// what gets placed where. For JIT clients, this is the subset of -// JITMemoryManager required for dynamic loading of binaries. -// -// FIXME: As the RuntimeDyld fills out, additional routines will be needed -// for the varying types of objects to be allocated. -class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; -public: - RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly) = 0; - - /// This method returns the address of the specified function. 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 returns a null pointer. Otherwise, it prints a - /// message to stderr and aborts. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) = 0; - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool applyPermissions(std::string *ErrMsg = 0) = 0; - - /// Register the EH frames with the runtime so that c++ exceptions work. The - /// default implementation does nothing. Look at SectionMemoryManager for one - /// that uses __register_frame. - virtual void registerEHFrames(StringRef SectionData); -}; - class RuntimeDyld { RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; @@ -113,9 +64,16 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); - StringRef getErrorString(); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); + + void deregisterEHFrames(); - StringRef getEHFrameSection(); + StringRef getErrorString(); }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 84a4e08cbb5c0..fd6e41f91ffb4 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" @@ -33,9 +33,9 @@ namespace llvm { /// Any client using this memory manager MUST ensure that section-specific /// page permissions have been applied before attempting to execute functions /// in the JITed object. Permissions can be applied either by calling -/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions +/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. -class SectionMemoryManager : public JITMemoryManager { +class SectionMemoryManager : public RTDyldMemoryManager { SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; @@ -49,7 +49,8 @@ public: /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, + StringRef SectionName); /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. @@ -58,30 +59,21 @@ public: /// a default alignment of 16 will be used. virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly); - /// \brief Applies section-specific memory permissions. + /// \brief Update section-specific memory permissions and other attributes. /// /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation /// to decide whether or not to act on this method. The memory manager will /// typically allocate all sections as read-write and then apply specific /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. /// /// \returns true if an error occurred, false otherwise. - virtual bool applyPermissions(std::string *ErrMsg = 0); - - void registerEHFrames(StringRef SectionData); - - /// This method returns the address of the specified function. As such it is - /// only useful for resolving library symbols, not code generated symbols. - /// - /// If \p AbortOnFailure is false and no function with the given name is - /// found, this function returns a null pointer. Otherwise, it prints a - /// message to stderr and aborts. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + virtual bool finalizeMemory(std::string *ErrMsg = 0); /// \brief Invalidate instruction cache for code sections. /// @@ -89,7 +81,7 @@ public: /// explicit cache flush, otherwise JIT code manipulations (like resolved /// relocations) will get to the data cache but not to the instruction cache. /// - /// This method is called from applyPermissions. + /// This method is called from finalizeMemory. virtual void invalidateInstructionCache(); private: @@ -108,66 +100,6 @@ private: MemoryGroup CodeMem; MemoryGroup RWDataMem; MemoryGroup RODataMem; - -public: - /// - /// Functions below are not used by MCJIT or RuntimeDyld, but must be - /// implemented because they are declared as pure virtuals in the base class. - /// - - virtual void setMemoryWritable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setMemoryExecutable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setPoisonMemory(bool poison) { - llvm_unreachable("Unexpected call!"); - } - virtual void AllocateGOT() { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *getGOTBase() const { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize){ - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, - unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void deallocateFunctionBody(void *Body) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *startExceptionTable(const Function *F, - uintptr_t &ActualSize) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t *FrameRegister) { - llvm_unreachable("Unexpected call!"); - } - virtual void deallocateExceptionTable(void *ET) { - llvm_unreachable("Unexpected call!"); - } }; } diff --git a/include/llvm/GVMaterializer.h b/include/llvm/GVMaterializer.h index 1e5c4263d49ba..8efe50ae94ba3 100644 --- a/include/llvm/GVMaterializer.h +++ b/include/llvm/GVMaterializer.h @@ -18,7 +18,7 @@ #ifndef LLVM_GVMATERIALIZER_H #define LLVM_GVMATERIALIZER_H -#include +#include "llvm/Support/system_error.h" namespace llvm { @@ -41,11 +41,9 @@ public: /// 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. + /// Materialize - make sure the given GlobalValue is fully read. /// - virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0) = 0; + virtual error_code Materialize(GlobalValue *GV) = 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 @@ -55,10 +53,8 @@ public: 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; + virtual error_code MaterializeModule(Module *M) = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 40d61ff6854b0..eb6ed46b473e9 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -82,6 +82,11 @@ public: /// its containing function. bool hasReturnedAttr() const; + /// \brief Return true if this argument has the readonly or readnone attribute + /// on it in its containing function. + bool onlyReadsMemory() const; + + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 2c7da6485dce2..c23ba0f73c58b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include @@ -67,7 +68,10 @@ public: ///< stored as log2 of alignment with +1 bias ///< 0 means unaligned (different from align(1)) AlwaysInline, ///< inline=always + Builtin, ///< Callee is recognized as a builtin, despite + ///< nobuiltin attribute on its declaration. ByVal, ///< Pass structure by value + Cold, ///< Marks function as being in a cold path. InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register MinSize, ///< Function must be optimized for size first @@ -85,6 +89,7 @@ public: NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack OptimizeForSize, ///< opt_size + OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory Returned, ///< Return value is always equal to this argument @@ -196,7 +201,7 @@ public: /// index `1'. class AttributeSet { public: - enum AttrIndex { + enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) { ReturnIndex = 0U, FunctionIndex = ~0U }; @@ -247,6 +252,8 @@ public: /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; + AttributeSet addAttribute(LLVMContext &C, unsigned Index, + StringRef Kind, StringRef Value) const; /// \brief Add attributes to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 6f3ab20886557..4437af255748b 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -51,6 +51,13 @@ namespace CallingConv { // (HiPE). HiPE = 11, + // WebKit JS - Calling convention for stack based JavaScript calls + WebKit_JS = 12, + + // AnyReg - Calling convention for dynamic register based calls (e.g. + // stackmap and patchpoint intrinsics). + AnyReg = 13, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, @@ -93,13 +100,6 @@ namespace CallingConv { /// 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, - /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. /// No lowering or expansion of arguments. /// Structures are passed as a pointer to a struct with the byval attribute. @@ -119,8 +119,17 @@ namespace CallingConv { SPIR_KERNEL = 76, /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins - Intel_OCL_BI = 77 + Intel_OCL_BI = 77, + + /// \brief The C convention as specified in the x86-64 supplement to the + /// System V ABI, used on most non-Windows systems. + X86_64_SysV = 78, + /// \brief The C convention as implemented on Windows/x86-64. This + /// convention differs from the more common \c X86_64_SysV convention + /// in a number of ways, most notably in that XMM registers used to pass + /// arguments are shadowed by GPRs, and vice versa. + X86_64_Win64 = 79 }; } // End CallingConv namespace diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 2f29f5459468f..dac20c9ec5c00 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -112,7 +112,6 @@ public: /// 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(); @@ -121,7 +120,6 @@ public: /// 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(); @@ -864,6 +862,7 @@ public: static Constant *getPtrToInt(Constant *C, Type *Ty); static Constant *getIntToPtr(Constant *C, Type *Ty); static Constant *getBitCast (Constant *C, Type *Ty); + static Constant *getAddrSpaceCast(Constant *C, Type *Ty); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -944,12 +943,20 @@ public: Type *Ty ///< The type to trunc or bitcast C to ); - /// @brief Create a BitCast or a PtrToInt cast constant expression + /// @brief Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant + /// expression. static Constant *getPointerCast( Constant *C, ///< The pointer value to be casted (operand 0) Type *Ty ///< The type to which cast should be made ); + /// @brief Create a BitCast or AddrSpaceCast for a pointer type depending on + /// the address space. + static Constant *getPointerBitCastOrAddrSpaceCast( + Constant *C, ///< The constant to addrspacecast or bitcast + Type *Ty ///< The type to bitcast or addrspacecast C to + ); + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( Constant *C, ///< The integer constant to be casted @@ -1081,8 +1088,8 @@ public: /// as this ConstantExpr. The instruction is not linked to any basic block. /// /// A better approach to this could be to have a constructor for Instruction - /// which would take a ConstantExpr parameter, but that would have spread - /// implementation details of ConstantExpr outside of Constants.cpp, which + /// which would take a ConstantExpr parameter, but that would have spread + /// implementation details of ConstantExpr outside of Constants.cpp, which /// would make it harder to remove ConstantExprs altogether. Instruction *getAsInstruction(); diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index b0def6be3f4db..10630a262008b 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -237,13 +237,14 @@ public: /// Layout pointer alignment /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerABIAlignment(unsigned AS = 0) const { + unsigned getPointerABIAlignment(unsigned AS = 0) const { DenseMap::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); } return val->second.ABIAlign; } + /// Return target's alignment for stack-based pointers /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. @@ -257,7 +258,7 @@ public: /// Layout pointer size /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const { + unsigned getPointerSize(unsigned AS = 0) const { DenseMap::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); @@ -267,9 +268,21 @@ public: /// Layout pointer size, in bits /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSizeInBits(unsigned AS = 0) const { + unsigned getPointerSizeInBits(unsigned AS = 0) const { return getPointerSize(AS) * 8; } + + /// Layout pointer size, in bits, based on the type. If this function is + /// called with a pointer type, then the type size of the pointer is returned. + /// If this function is called with a vector of pointers, then the type size + /// of the pointer is returned. This should only be called with a pointer or + /// vector of pointers. + unsigned getPointerTypeSizeInBits(Type *) const; + + unsigned getPointerTypeSize(Type *Ty) const { + return getPointerTypeSizeInBits(Ty) / 8; + } + /// Size examples: /// /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] @@ -356,6 +369,17 @@ public: /// least as big as Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; + /// getLargestLegalIntType - Return the largest legal integer type, or null if + /// none are set. + Type *getLargestLegalIntType(LLVMContext &C) const { + unsigned LargestSize = getLargestLegalIntTypeSize(); + return (LargestSize == 0) ? 0 : Type::getIntNTy(C, LargestSize); + } + + /// getLargestLegalIntType - Return the size of largest legal integer type + /// size, or 0 if none are set. + unsigned getLargestLegalIntTypeSize() const; + /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef Indices) const; @@ -438,7 +462,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { case Type::LabelTyID: return getPointerSizeInBits(0); case Type::PointerTyID: - return getPointerSizeInBits(cast(Ty)->getAddressSpace()); + return getPointerSizeInBits(Ty->getPointerAddressSpace()); case Type::ArrayTyID: { ArrayType *ATy = cast(Ty); return ATy->getNumElements() * @@ -448,7 +472,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { // Get the layout annotation... which is lazily created on demand. return getStructLayout(cast(Ty))->getSizeInBits(); case Type::IntegerTyID: - return cast(Ty)->getBitWidth(); + return Ty->getIntegerBitWidth(); case Type::HalfTyID: return 16; case Type::FloatTyID: diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index f97929f658548..bba7ecdd2372d 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -159,37 +159,44 @@ public: /// 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); + return static_cast(getSubclassDataFromValue() >> 2); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 1) | - (static_cast(CC) << 1)); + setValueSubclassData((getSubclassDataFromValue() & 3) | + (static_cast(CC) << 2)); } - /// getAttributes - Return the attribute list for this Function. - /// + /// @brief Return the attribute list for this Function. AttributeSet getAttributes() const { return AttributeSets; } - /// setAttributes - Set the attribute list for this Function. - /// + /// @brief Set the attribute list for this Function. void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Add function attributes to this function. void addFnAttr(Attribute::AttrKind N) { setAttributes(AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, N)); } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Remove function attributes from this function. + void removeFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, N)); + } + + /// @brief Add function attributes to this function. void addFnAttr(StringRef Kind) { setAttributes( AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, Kind)); } + void addFnAttr(StringRef Kind, StringRef Value) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind, Value)); + } - /// \brief Return true if the function has the attribute. + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } @@ -197,6 +204,14 @@ public: return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } + /// @brief Return the attribute for the given attribute kind. + Attribute getFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + Attribute getFnAttribute(StringRef Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -303,6 +318,21 @@ public: addAttribute(n, Attribute::NoCapture); } + bool doesNotAccessMemory(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::ReadNone); + } + void setDoesNotAccessMemory(unsigned n) { + addAttribute(n, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned n) const { + return doesNotAccessMemory(n) || + AttributeSets.hasAttribute(n, Attribute::ReadOnly); + } + void setOnlyReadsMemory(unsigned n) { + addAttribute(n, Attribute::ReadOnly); + } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. void copyAttributesFrom(const GlobalValue *Src); @@ -397,6 +427,13 @@ public: size_t arg_size() const; bool arg_empty() const; + bool hasPrefixData() const { + return getSubclassDataFromValue() & 2; + } + + Constant *getPrefixData() const; + void setPrefixData(Constant *PrefixData); + /// 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 diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 883814a323717..fec61a7ceaf1a 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -66,14 +66,25 @@ public: } /// getAliasedGlobal() - Aliasee can be either global or bitcast of /// global. This method retrives the global for both aliasee flavours. - const GlobalValue *getAliasedGlobal() const; + GlobalValue *getAliasedGlobal(); + const GlobalValue *getAliasedGlobal() const { + return const_cast(this)->getAliasedGlobal(); + } /// 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; + GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true); + const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const { + return const_cast(this)->resolveAliasedGlobal(stopOnWeak); + } + + static bool isValidLinkage(LinkageTypes L) { + return isExternalLinkage(L) || isLocalLinkage(L) || + isWeakLinkage(L) || isLinkOnceLinkage(L); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 260302a594b42..4f20a31a294b5 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -35,7 +35,6 @@ public: AvailableExternallyLinkage, ///< Available for inspection, not emission. LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. - LinkOnceODRAutoHideLinkage, ///< Like LinkOnceODRLinkage but addr not taken. 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 @@ -123,12 +122,7 @@ public: return Linkage == AvailableExternallyLinkage; } static bool isLinkOnceLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage; - } - static bool isLinkOnceODRAutoHideLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceODRAutoHideLinkage; + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } static bool isWeakLinkage(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; @@ -192,7 +186,6 @@ public: Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage || Linkage == CommonLinkage || Linkage == ExternalWeakLinkage || Linkage == LinkerPrivateWeakLinkage; @@ -205,9 +198,6 @@ public: bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } - bool hasLinkOnceODRAutoHideLinkage() const { - return isLinkOnceODRAutoHideLinkage(Linkage); - } bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } @@ -239,6 +229,15 @@ public: /// create a GlobalValue) from the GlobalValue Src to this one. virtual void copyAttributesFrom(const GlobalValue *Src); + /// 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 Name) { + if (!Name.empty() && Name[0] == '\1') + return Name.substr(1); + return Name; + } + /// @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 diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index bfed50786ea0b..660092df3dee0 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -84,9 +84,7 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// 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. + /// Definitions have initializers, declarations don't. /// inline bool hasInitializer() const { return !isDeclaration(); } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index f11d3b4e0b270..8d1432d6c9217 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -25,6 +25,7 @@ #include "llvm/IR/Operator.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ConstantFolder.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class MDNode; @@ -49,17 +50,16 @@ protected: class IRBuilderBase { DebugLoc CurDbgLocation; protected: - /// Save the current debug location here while we are suppressing - /// line table entries. - llvm::DebugLoc SavedDbgLocation; - BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; + + MDNode *DefaultFPMathTag; + FastMathFlags FMF; public: - IRBuilderBase(LLVMContext &context) - : Context(context) { + IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = 0) + : Context(context), DefaultFPMathTag(FPMathTag), FMF() { ClearInsertionPoint(); } @@ -71,6 +71,7 @@ public: /// inserted into a block. void ClearInsertionPoint() { BB = 0; + InsertPt = 0; } BasicBlock *GetInsertBlock() const { return BB; } @@ -89,6 +90,7 @@ public: void SetInsertPoint(Instruction *I) { BB = I->getParent(); InsertPt = I; + assert(I != BB->end() && "Can't read debug loc from end()"); SetCurrentDebugLocation(I->getDebugLoc()); } @@ -117,23 +119,6 @@ public: CurDbgLocation = L; } - /// \brief Temporarily suppress DebugLocations from being attached - /// to emitted instructions, until the next call to - /// SetCurrentDebugLocation() or EnableDebugLocations(). Use this - /// if you want an instruction to be counted towards the prologue or - /// if there is no useful source location. - void DisableDebugLocations() { - llvm::DebugLoc Empty; - SavedDbgLocation = getCurrentDebugLocation(); - SetCurrentDebugLocation(Empty); - } - - /// \brief Restore the previously saved DebugLocation. - void EnableDebugLocations() { - assert(CurDbgLocation.isUnknown()); - SetCurrentDebugLocation(SavedDbgLocation); - } - /// \brief Get location information used by debugging information. DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } @@ -188,6 +173,68 @@ public: ClearInsertionPoint(); } + /// \brief Get the floating point math metadata being used. + MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + + /// \brief Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// \brief Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + + /// \brief Set the floating point math metadata to be used. + void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + + /// \brief Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + + //===--------------------------------------------------------------------===// + // RAII helpers. + //===--------------------------------------------------------------------===// + + // \brief RAII object that stores the current insertion point and restores it + // when the object is destroyed. This includes the debug location. + class InsertPointGuard { + IRBuilderBase &Builder; + AssertingVH Block; + BasicBlock::iterator Point; + DebugLoc DbgLoc; + + InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + + public: + InsertPointGuard(IRBuilderBase &B) + : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()), + DbgLoc(B.getCurrentDebugLocation()) {} + + ~InsertPointGuard() { + Builder.restoreIP(InsertPoint(Block, Point)); + Builder.SetCurrentDebugLocation(DbgLoc); + } + }; + + // \brief RAII object that stores the current fast math settings and restores + // them when the object is destroyed. + class FastMathFlagGuard { + IRBuilderBase &Builder; + FastMathFlags FMF; + MDNode *FPMathTag; + + FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard &operator=( + const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + + public: + FastMathFlagGuard(IRBuilderBase &B) + : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {} + + ~FastMathFlagGuard() { + Builder.FMF = FMF; + Builder.DefaultFPMathTag = FPMathTag; + } + }; + //===--------------------------------------------------------------------===// // Miscellaneous creation methods. //===--------------------------------------------------------------------===// @@ -290,7 +337,7 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { + IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { return DL->getIntPtrType(Context, AddrSpace); } @@ -373,76 +420,52 @@ template > class IRBuilder : public IRBuilderBase, public Inserter { T Folder; - MDNode *DefaultFPMathTag; - FastMathFlags FMF; public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), MDNode *FPMathTag = 0) - : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) { } explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) - : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(C, FPMathTag), Folder() { } explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB); } explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(U->getContext(), FPMathTag), Folder() { SetInsertPoint(U); SetCurrentDebugLocation(cast(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB, IP); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB, IP); } /// \brief Get the constant folder being used. const T &getFolder() { return Folder; } - /// \brief Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// \brief Get the flags to be applied to created floating point ops - FastMathFlags getFastMathFlags() const { return FMF; } - - /// \brief Clear the fast-math flags. - void clearFastMathFlags() { FMF.clear(); } - - /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used. - void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// \brief Set the fast-math flags to be used with generated fp-math operators - void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - /// \brief Return true if this builder is configured to actually add the /// requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } @@ -1110,6 +1133,10 @@ public: const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } + Value *CreateAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); + } Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 33e4ab8522d1b..3398a83e365e1 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -197,7 +197,7 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 3e6903cb52d75..e12bb03a403f0 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -531,6 +531,12 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast between these types is valid + static bool isBitCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + 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 @@ -568,7 +574,7 @@ public: Instruction::CastOps Opcode, ///< Opcode of cast Type *SrcTy, ///< SrcTy of cast Type *DstTy, ///< DstTy of cast - Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *IntPtrTy ///< Integer type corresponding to Ptr types ); /// @brief Determine if this cast is a no-op cast. @@ -698,7 +704,7 @@ public: /// @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()); @@ -715,15 +721,15 @@ public: 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. @@ -821,7 +827,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } - + /// @brief Create a result type for fcmp/icmp static Type* makeCmpResultType(Type* opnd_type) { if (VectorType* vt = dyn_cast(opnd_type)) { diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def index e59a0528e90f1..d46314cc761db 100644 --- a/include/llvm/IR/Instruction.def +++ b/include/llvm/IR/Instruction.def @@ -154,25 +154,26 @@ HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast - LAST_CAST_INST(44) +HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(45) // Other operators... - FIRST_OTHER_INST(45) -HANDLE_OTHER_INST(45, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(46, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(47, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(48, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(49, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(50, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(51, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(52, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(53, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(54, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(55, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(56, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(57, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(58, LandingPad, LandingPadInst) // Landing pad instruction. - LAST_OTHER_INST(58) + FIRST_OTHER_INST(46) +HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(59) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 7e29699f73d94..0843d8fca3e20 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -23,8 +23,6 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/IntegersSubset.h" -#include "llvm/Support/IntegersSubsetMapping.h" #include namespace llvm { @@ -911,6 +909,18 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// must be identical types. /// \brief Represent an integer comparison operator. class ICmpInst: public CmpInst { + void AssertOK() { + assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && + getPredicate() <= 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()->isPtrOrPtrVectorTy()) && + "Invalid operand types for ICmp instruction"); + } + protected: /// \brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; @@ -925,15 +935,9 @@ public: ) : 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()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with insert-at-end semantics. @@ -946,15 +950,9 @@ public: ) : 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()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with no-insertion semantics @@ -965,15 +963,9 @@ public: 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()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. @@ -1278,7 +1270,11 @@ public: void removeAttribute(unsigned i, Attribute attr); /// \brief Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -1288,6 +1284,13 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -1378,6 +1381,9 @@ public: return isa(V) && classof(cast(V)); } private: + + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -2443,31 +2449,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) class SwitchInst : public TerminatorInst { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; unsigned ReservedSpace; - // Operands format: // 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 - - // Store case values separately from operands list. We needn't User-Use - // concept here, since it is just a case value, it will always constant, - // and case value couldn't reused with another instructions/values. - // Additionally: - // It allows us to use custom type for case values that is not inherited - // from Value. Since case value is a complex type that implements - // the subset of integers, we needn't extract sub-constants within - // slow getAggregateElement method. - // For case values we will use std::list to by two reasons: - // 1. It allows to add/remove cases without whole collection reallocation. - // 2. In most of cases we needn't random access. - // Currently case values are also stored in Operands List, but it will moved - // out in future commits. - typedef std::list Subsets; - typedef Subsets::iterator SubsetsIt; - typedef Subsets::const_iterator SubsetsConstIt; - - Subsets TheSubsets; - SwitchInst(const SwitchInst &SI); void init(Value *Value, BasicBlock *Default, unsigned NumReserved); void growOperands(); @@ -2492,25 +2477,121 @@ protected: virtual SwitchInst *clone_impl() const; public: - // FIXME: Currently there are a lot of unclean template parameters, - // we need to make refactoring in future. - // All these parameters are used to implement both iterator and const_iterator - // without code duplication. - // SwitchInstTy may be "const SwitchInst" or "SwitchInst" - // ConstantIntTy may be "const ConstantInt" or "ConstantInt" - // SubsetsItTy may be SubsetsConstIt or SubsetsIt - // BasicBlockTy may be "const BasicBlock" or "BasicBlock" - template - class CaseIteratorT; - - typedef CaseIteratorT ConstCaseIt; - class CaseIt; - // -2 static const unsigned DefaultPseudoIndex = static_cast(~0L-1); + template + class CaseIteratorT { + protected: + + SwitchInstTy *SI; + unsigned Index; + + public: + + typedef CaseIteratorT Self; + + /// Initializes case iterator for given SwitchInst and for given + /// case number. + CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { + this->SI = SI; + Index = CaseNum; + } + + /// Initializes case iterator for given SwitchInst and for given + /// TerminatorInst's successor index. + static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { + assert(SuccessorIndex < SI->getNumSuccessors() && + "Successor index # out of range!"); + return SuccessorIndex != 0 ? + Self(SI, SuccessorIndex - 1) : + Self(SI, DefaultPseudoIndex); + } + + /// Resolves case value for current case. + ConstantIntTy *getCaseValue() { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + return reinterpret_cast(SI->getOperand(2 + Index*2)); + } + + /// Resolves successor for current case. + BasicBlockTy *getCaseSuccessor() { + assert((Index < SI->getNumCases() || + Index == DefaultPseudoIndex) && + "Index out the number of cases."); + return SI->getSuccessor(getSuccessorIndex()); + } + + /// Returns number of current case. + unsigned getCaseIndex() const { return Index; } + + /// Returns TerminatorInst's successor index for current case successor. + unsigned getSuccessorIndex() const { + assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && + "Index out the number of cases."); + return Index != DefaultPseudoIndex ? Index + 1 : 0; + } + + Self operator++() { + // Check index correctness after increment. + // Note: Index == getNumCases() means end(). + assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); + ++Index; + return *this; + } + Self operator++(int) { + Self tmp = *this; + ++(*this); + return tmp; + } + Self operator--() { + // Check index correctness after decrement. + // Note: Index == getNumCases() means end(). + // Also allow "-1" iterator here. That will became valid after ++. + assert((Index == 0 || Index-1 <= SI->getNumCases()) && + "Index out the number of cases."); + --Index; + return *this; + } + Self operator--(int) { + Self tmp = *this; + --(*this); + return tmp; + } + bool operator==(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index == Index; + } + bool operator!=(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index != Index; + } + }; + + typedef CaseIteratorT + ConstCaseIt; + + class CaseIt : public CaseIteratorT { + + typedef CaseIteratorT ParentTy; + + public: + + CaseIt(const ParentTy& Src) : ParentTy(Src) {} + CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} + + /// Sets the new value for current case. + void setValue(ConstantInt *V) { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + SI->setOperand(2 + Index*2, reinterpret_cast(V)); + } + + /// Sets the new successor for current case. + void setSuccessor(BasicBlock *S) { + SI->setSuccessor(getSuccessorIndex(), S); + } + }; + static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore = 0) { return new SwitchInst(Value, Default, NumCases, InsertBefore); @@ -2546,23 +2627,23 @@ public: /// Returns a read/write iterator that points to the first /// case in SwitchInst. CaseIt case_begin() { - return CaseIt(this, 0, TheSubsets.begin()); + return CaseIt(this, 0); } /// Returns a read-only iterator that points to the first /// case in the SwitchInst. ConstCaseIt case_begin() const { - return ConstCaseIt(this, 0, TheSubsets.begin()); + return ConstCaseIt(this, 0); } /// Returns a read/write iterator that points one past the last /// in the SwitchInst. CaseIt case_end() { - return CaseIt(this, getNumCases(), TheSubsets.end()); + return CaseIt(this, getNumCases()); } /// Returns a read-only iterator that points one past the last /// in the SwitchInst. ConstCaseIt case_end() const { - return ConstCaseIt(this, getNumCases(), TheSubsets.end()); + return ConstCaseIt(this, getNumCases()); } /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt @@ -2570,10 +2651,10 @@ public: /// Also note, that increment and decrement also causes an assertion and /// makes iterator invalid. CaseIt case_default() { - return CaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return CaseIt(this, DefaultPseudoIndex); } ConstCaseIt case_default() const { - return ConstCaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return ConstCaseIt(this, DefaultPseudoIndex); } /// findCaseValue - Search all of the case values for the specified constant. @@ -2582,13 +2663,13 @@ public: /// that it is handled by the default handler. CaseIt findCaseValue(const ConstantInt *C) { for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } ConstCaseIt findCaseValue(const ConstantInt *C) const { for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } @@ -2609,25 +2690,18 @@ public: } /// addCase - Add an entry to the switch instruction... - /// @deprecated /// Note: /// This action invalidates case_end(). Old case_end() iterator will /// point to the added case. void addCase(ConstantInt *OnVal, BasicBlock *Dest); - /// addCase - Add an entry to the switch instruction. - /// Note: - /// This action invalidates case_end(). Old case_end() iterator will - /// point to the added case. - void addCase(IntegersSubset& OnVal, BasicBlock *Dest); - /// removeCase - This method removes the specified case and its successor /// from the switch instruction. Note that this operation may reorder the /// remaining cases at index idx and above. /// Note: /// This action invalidates iterators for all cases following the one removed, /// including the case_end() iterator. - void removeCase(CaseIt& i); + void removeCase(CaseIt i); unsigned getNumSuccessors() const { return getNumOperands()/2; } BasicBlock *getSuccessor(unsigned idx) const { @@ -2639,192 +2713,7 @@ public: setOperand(idx*2+1, (Value*)NewSucc); } - uint16_t hash() const { - uint32_t NumberOfCases = (uint32_t)getNumCases(); - uint16_t Hash = (0xFFFF & NumberOfCases) ^ (NumberOfCases >> 16); - for (ConstCaseIt i = case_begin(), e = case_end(); - i != e; ++i) { - uint32_t NumItems = (uint32_t)i.getCaseValueEx().getNumItems(); - Hash = (Hash << 1) ^ (0xFFFF & NumItems) ^ (NumItems >> 16); - } - return Hash; - } - - // Case iterators definition. - - template - class CaseIteratorT { - protected: - - SwitchInstTy *SI; - unsigned Index; - SubsetsItTy SubsetIt; - - /// Initializes case iterator for given SwitchInst and for given - /// case number. - friend class SwitchInst; - CaseIteratorT(SwitchInstTy *SI, unsigned SuccessorIndex, - SubsetsItTy CaseValueIt) { - this->SI = SI; - Index = SuccessorIndex; - this->SubsetIt = CaseValueIt; - } - - public: - typedef typename SubsetsItTy::reference IntegersSubsetRef; - typedef CaseIteratorT Self; - - CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { - this->SI = SI; - Index = CaseNum; - SubsetIt = SI->TheSubsets.begin(); - std::advance(SubsetIt, CaseNum); - } - - - /// Initializes case iterator for given SwitchInst and for given - /// TerminatorInst's successor index. - static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { - assert(SuccessorIndex < SI->getNumSuccessors() && - "Successor index # out of range!"); - return SuccessorIndex != 0 ? - Self(SI, SuccessorIndex - 1) : - Self(SI, DefaultPseudoIndex); - } - - /// Resolves case value for current case. - /// @deprecated - ConstantIntTy *getCaseValue() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetRef CaseRanges = *SubsetIt; - - // FIXME: Currently we work with ConstantInt based cases. - // So return CaseValue as ConstantInt. - return CaseRanges.getSingleNumber(0).toConstantInt(); - } - - /// Resolves case value for current case. - IntegersSubsetRef getCaseValueEx() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - return *SubsetIt; - } - - /// Resolves successor for current case. - BasicBlockTy *getCaseSuccessor() { - assert((Index < SI->getNumCases() || - Index == DefaultPseudoIndex) && - "Index out the number of cases."); - return SI->getSuccessor(getSuccessorIndex()); - } - - /// Returns number of current case. - unsigned getCaseIndex() const { return Index; } - - /// Returns TerminatorInst's successor index for current case successor. - unsigned getSuccessorIndex() const { - assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && - "Index out the number of cases."); - return Index != DefaultPseudoIndex ? Index + 1 : 0; - } - - Self operator++() { - // Check index correctness after increment. - // Note: Index == getNumCases() means end(). - assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); - ++Index; - if (Index == 0) - SubsetIt = SI->TheSubsets.begin(); - else - ++SubsetIt; - return *this; - } - Self operator++(int) { - Self tmp = *this; - ++(*this); - return tmp; - } - Self operator--() { - // Check index correctness after decrement. - // Note: Index == getNumCases() means end(). - // Also allow "-1" iterator here. That will became valid after ++. - unsigned NumCases = SI->getNumCases(); - assert((Index == 0 || Index-1 <= NumCases) && - "Index out the number of cases."); - --Index; - if (Index == NumCases) { - SubsetIt = SI->TheSubsets.end(); - return *this; - } - - if (Index != -1U) - --SubsetIt; - - return *this; - } - Self operator--(int) { - Self tmp = *this; - --(*this); - return tmp; - } - bool operator==(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index == Index; - } - bool operator!=(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index != Index; - } - }; - - class CaseIt : public CaseIteratorT { - typedef CaseIteratorT - ParentTy; - - protected: - friend class SwitchInst; - CaseIt(SwitchInst *SI, unsigned CaseNum, SubsetsIt SubsetIt) : - ParentTy(SI, CaseNum, SubsetIt) {} - - void updateCaseValueOperand(IntegersSubset& V) { - SI->setOperand(2 + Index*2, reinterpret_cast((Constant*)V)); - } - - public: - - CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} - - CaseIt(const ParentTy& Src) : ParentTy(Src) {} - - /// Sets the new value for current case. - /// @deprecated. - void setValue(ConstantInt *V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetToBB Mapping; - // FIXME: Currently we work with ConstantInt based cases. - // So inititalize IntItem container directly from ConstantInt. - Mapping.add(IntItem::fromConstantInt(V)); - *SubsetIt = Mapping.getCase(); - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new value for current case. - void setValueEx(IntegersSubset& V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - *SubsetIt = V; - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new successor for current case. - void setSuccessor(BasicBlock *S) { - SI->setSuccessor(getSuccessorIndex(), S); - } - }; - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Switch; } @@ -3023,8 +2912,12 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); - /// \brief Determine whether this call has the NoAlias attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -3034,6 +2927,15 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have + // to check it by hand. + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -3140,6 +3042,8 @@ private: virtual unsigned getNumSuccessorsV() const; virtual void setSuccessorV(unsigned idx, BasicBlock *B); + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -3711,6 +3615,43 @@ public: } }; +//===----------------------------------------------------------------------===// +// AddrSpaceCastInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a conversion between pointers from +/// one address space to another. +class AddrSpaceCastInst : public CastInst { +protected: + /// \brief Clone an identical AddrSpaceCastInst + virtual AddrSpaceCastInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + AddrSpaceCastInst( + Value *S, ///< The value to be casted + 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 + AddrSpaceCastInst( + Value *S, ///< The value to be casted + 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 Instruction *I) { + return I->getOpcode() == AddrSpaceCast; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index c81d110e3b4b8..473e525d9b942 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -77,7 +77,7 @@ namespace Intrinsic { /// getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { - Void, MMX, Metadata, Half, Float, Double, + Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendVecArgument, TruncVecArgument } Kind; diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e252664e45cf2..ded6cc12bf192 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -55,6 +55,18 @@ class NoCapture : IntrinsicProperty { int ArgNo = argNo; } +// ReadOnly - The specified argument pointer is not written to through the +// pointer by the intrinsic. +class ReadOnly : IntrinsicProperty { + int ArgNo = argNo; +} + +// ReadNone - The specified argument pointer is not dereferenced by the +// intrinsic. +class ReadNone : IntrinsicProperty { + int ArgNo = argNo; +} + def IntrNoReturn : IntrinsicProperty; //===----------------------------------------------------------------------===// @@ -128,6 +140,7 @@ def llvm_v8i1_ty : LLVMType; // 8 x i1 def llvm_v16i1_ty : LLVMType; // 16 x i1 def llvm_v32i1_ty : LLVMType; // 32 x i1 def llvm_v64i1_ty : LLVMType; // 64 x i1 +def llvm_v1i8_ty : LLVMType; // 1 x i8 def llvm_v2i8_ty : LLVMType; // 2 x i8 def llvm_v4i8_ty : LLVMType; // 4 x i8 def llvm_v8i8_ty : LLVMType; // 8 x i8 @@ -153,10 +166,15 @@ def llvm_v4i64_ty : LLVMType; // 4 x i64 def llvm_v8i64_ty : LLVMType; // 8 x i64 def llvm_v16i64_ty : LLVMType; // 16 x i64 +def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) +def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) +def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) +def llvm_v1f32_ty : LLVMType; // 1 x float 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_v16f32_ty : LLVMType; // 16 x float +def llvm_v1f64_ty : LLVMType; // 1 x double def llvm_v2f64_ty : LLVMType; // 2 x double def llvm_v4f64_ty : LLVMType; // 4 x double def llvm_v8f64_ty : LLVMType; // 8 x double @@ -246,6 +264,8 @@ 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], []>; +def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], + [IntrReadWriteArgMem]>; //===------------------- Standard C Library Intrinsics --------------------===// // @@ -253,11 +273,13 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], - [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<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>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<1>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], @@ -279,11 +301,14 @@ let Properties = [IntrReadMem] in { def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_copysign : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_ceil : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_trunc : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; } let Properties = [IntrNoMem] in { @@ -303,7 +328,7 @@ def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking -def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty], [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; @@ -347,6 +372,9 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; +// __builtin_unwind_init is an undocumented GCC intrinsic that causes all +// callee-saved registers to be saved and restored (regardless of whether they +// are used) in the calling function. It is used by libgcc_eh. def int_eh_unwind_init: Intrinsic<[]>, GCCBuiltin<"__builtin_unwind_init">; @@ -427,6 +455,19 @@ def int_invariant_end : Intrinsic<[], llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<2>]>; +//===------------------------ Stackmap Intrinsics -------------------------===// +// +def int_experimental_stackmap : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; +def int_experimental_patchpoint_void : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; +def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -477,6 +518,7 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], include "llvm/IR/IntrinsicsPowerPC.td" include "llvm/IR/IntrinsicsX86.td" include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsAArch64.td" include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td new file mode 100644 index 0000000000000..68af8c1164ec1 --- /dev/null +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -0,0 +1,388 @@ +//===- IntrinsicsAArch64.td - Defines AArch64 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 AArch64-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + +// Vector Absolute Compare (Floating Point) +def int_aarch64_neon_vacgeq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vacgtq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +// Vector saturating accumulate +def int_aarch64_neon_suqadd : Neon_2Arg_Intrinsic; +def int_aarch64_neon_usqadd : Neon_2Arg_Intrinsic; + +// Vector Bitwise reverse +def int_aarch64_neon_rbit : Neon_1Arg_Intrinsic; + +// Vector extract and narrow +def int_aarch64_neon_xtn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Vector floating-point convert +def int_aarch64_neon_frintn : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fsqrt : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fcvtxn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtns : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtnu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtps : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtpu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtms : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtmu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtas : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtau : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzs : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Vector maxNum (Floating Point) +def int_aarch64_neon_vmaxnm : Neon_2Arg_Intrinsic; + +// Vector minNum (Floating Point) +def int_aarch64_neon_vminnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise maxNum (Floating Point) +def int_aarch64_neon_vpmaxnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise minNum (Floating Point) +def int_aarch64_neon_vpminnm : Neon_2Arg_Intrinsic; + +// Vector Multiply Extended and Scalar Multiply Extended (Floating Point) +def int_aarch64_neon_vmulx : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + +class Neon_N2V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N3V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N2V_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, llvm_i32_ty], + [IntrNoMem]>; + +// Vector rounding shift right by immediate (Signed) +def int_aarch64_neon_vsrshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vurshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vsqshlu : Neon_N2V_Intrinsic; + +def int_aarch64_neon_vsri : Neon_N3V_Intrinsic; +def int_aarch64_neon_vsli : Neon_N3V_Intrinsic; + +def int_aarch64_neon_vsqshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqrshrn : Neon_N2V_Narrow_Intrinsic; + +// Vector across +class Neon_Across_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +class Neon_2Arg_Across_Float_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_aarch64_neon_saddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_uaddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_smaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_umaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_sminv : Neon_Across_Intrinsic; +def int_aarch64_neon_uminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vaddv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxnmv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminnmv : Neon_Across_Intrinsic; + +// Vector Table Lookup. +def int_aarch64_neon_vtbl1 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl2 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbl3 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl4 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +// 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_aarch64_neon_vtbx1 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbx2 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx3 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx4 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +// Vector Load/store +def int_aarch64_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_aarch64_neon_vst1x2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// Scalar Add +def int_aarch64_neon_vaddds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vadddu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Sub +def int_aarch64_neon_vsubds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vsubdu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Shift +// Scalar Shift Left +def int_aarch64_neon_vshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Shift Left +def int_aarch64_neon_vqshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqshlu : Neon_2Arg_Intrinsic; + +// Scalar Shift Rouding Left +def int_aarch64_neon_vrshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vrshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Rounding Shift Left +def int_aarch64_neon_vqrshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqrshlu : Neon_2Arg_Intrinsic; + +// Scalar Reduce Pairwise Add. +def int_aarch64_neon_vpadd : + Intrinsic<[llvm_v1i64_ty], [llvm_v2i64_ty],[IntrNoMem]>; +def int_aarch64_neon_vpfadd : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfaddq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Max/Min. +def int_aarch64_neon_vpmax : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmaxq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmin : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpminq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Maxnm/Minnm. +def int_aarch64_neon_vpfmaxnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfmaxnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Signed Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Unsigned Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Exponent +def int_aarch64_neon_vrecpx : Neon_1Arg_Intrinsic; + +class Neon_Cmp_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], + [IntrNoMem]>; + +// Scalar Compare Equal +def int_aarch64_neon_vceq : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than or Equal +def int_aarch64_neon_vcge : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchs : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than or Equal +def int_aarch64_neon_vclez : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than +def int_aarch64_neon_vcltz : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than +def int_aarch64_neon_vcgt : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchi : Neon_Cmp_Intrinsic; + +// Scalar Compare Bitwise Test Bits +def int_aarch64_neon_vtstd : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than Or Equal +def int_aarch64_neon_vcage : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than +def int_aarch64_neon_vcagt : Neon_Cmp_Intrinsic; + +// Scalar Signed Saturating Accumulated of Unsigned Value +def int_aarch64_neon_vuqadd : Neon_2Arg_Intrinsic; + +// Scalar Unsigned Saturating Accumulated of Signed Value +def int_aarch64_neon_vsqadd : Neon_2Arg_Intrinsic; + +// Scalar Absolute Value +def int_aarch64_neon_vabs : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Absolute Difference +def int_aarch64_neon_vabd : Neon_2Arg_Intrinsic; + +// Scalar Negate Value +def int_aarch64_neon_vneg : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Signed Saturating Doubling Multiply-Add Long +def int_aarch64_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + +// Signed Saturating Doubling Multiply-Subtract Long +def int_aarch64_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + +class Neon_2Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_3Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +// Scalar Shift Right (Immediate) +def int_aarch64_neon_vshrds_n : Neon_2Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vshrdu_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Rounding Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vrsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vrsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Shift Left (Immediate) +def int_aarch64_neon_vshld_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Saturating Shift Left (Immediate) +def int_aarch64_neon_vqshls_n : Neon_N2V_Intrinsic; +def int_aarch64_neon_vqshlu_n : Neon_N2V_Intrinsic; + +// Scalar Signed Saturating Shift Left Unsigned (Immediate) +def int_aarch64_neon_vqshlus_n : Neon_N2V_Intrinsic; + +// Scalar Signed Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Signed Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_s32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_s64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_u32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_u64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_SHA_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v1i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_aarch64_neon_sha1c : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1m : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1p : Neon_SHA_Intrinsic; +} diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 93b1ae1dc887b..0b50d64aebc39 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -34,12 +34,20 @@ def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; //===----------------------------------------------------------------------===// -// Load and Store exclusive doubleword +// Load, Store and Clear exclusive + +def int_arm_ldrex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; +def int_arm_strex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; +def int_arm_clrex : Intrinsic<[]>; def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty], [IntrReadWriteArgMem]>; -def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], - [IntrReadArgMem]>; + llvm_ptr_ty]>; +def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; + +//===----------------------------------------------------------------------===// +// Data barrier instructions +def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // VFP @@ -88,6 +96,26 @@ def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +//===----------------------------------------------------------------------===// +// CRC32 + +def int_arm_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// HINT +def int_arm_sevl : Intrinsic<[], []>; + //===----------------------------------------------------------------------===// // Advanced SIMD (NEON) @@ -124,6 +152,8 @@ 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]>; +class Neon_CvtFPtoInt_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_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. @@ -158,7 +188,6 @@ let Properties = [IntrNoMem, Commutative] in { 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. @@ -170,17 +199,15 @@ let Properties = [IntrNoMem, Commutative] in { def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; - // Vector Multiply and Accumulate/Subtract. - 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; + def int_arm_neon_vmaxnm : Neon_2Arg_Intrinsic; // Vector Minimum. def int_arm_neon_vmins : Neon_2Arg_Intrinsic; def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + def int_arm_neon_vminnm : Neon_2Arg_Intrinsic; // Vector Reciprocal Step. def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; @@ -194,7 +221,6 @@ 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. @@ -314,6 +340,16 @@ 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 Integer +def int_arm_neon_vcvtau : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtas : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtnu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtns : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtpu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtps : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtmu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtms : Neon_CvtFPtoInt_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; @@ -347,6 +383,14 @@ def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; +// Vector Rounding +def int_arm_neon_vrintn : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintx : Neon_1Arg_Intrinsic; +def int_arm_neon_vrinta : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintz : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintm : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintp : Neon_1Arg_Intrinsic; + // De-interleaving vector loads from N-element structures. // Source operands are the address and alignment. def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], @@ -426,4 +470,21 @@ def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + +// Crypto instructions +def int_arm_neon_aesd : Neon_2Arg_Intrinsic; +def int_arm_neon_aese : Neon_2Arg_Intrinsic; +def int_arm_neon_aesimc : Neon_1Arg_Intrinsic; +def int_arm_neon_aesmc : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1h : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1su1 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha256su0 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha1c : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1m : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1p : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1su0: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h2: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256su1: Neon_3Arg_Intrinsic; + } // end TargetPrefix diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index a0987c815b5c7..42c58214151d8 100644 --- a/include/llvm/IR/IntrinsicsMips.td +++ b/include/llvm/IR/IntrinsicsMips.td @@ -386,4 +386,1372 @@ def int_mips_subuh_qb: GCCBuiltin<"__builtin_mips_subuh_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; def int_mips_subuh_r_qb: GCCBuiltin<"__builtin_mips_subuh_r_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// MIPS MSA + +//===----------------------------------------------------------------------===// +// Addition/subtraction + +def int_mips_add_a_b : GCCBuiltin<"__builtin_msa_add_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_h : GCCBuiltin<"__builtin_msa_add_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_w : GCCBuiltin<"__builtin_msa_add_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_d : GCCBuiltin<"__builtin_msa_add_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_a_b : GCCBuiltin<"__builtin_msa_adds_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_h : GCCBuiltin<"__builtin_msa_adds_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_w : GCCBuiltin<"__builtin_msa_adds_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_d : GCCBuiltin<"__builtin_msa_adds_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_s_b : GCCBuiltin<"__builtin_msa_adds_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_h : GCCBuiltin<"__builtin_msa_adds_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_w : GCCBuiltin<"__builtin_msa_adds_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_d : GCCBuiltin<"__builtin_msa_adds_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_u_b : GCCBuiltin<"__builtin_msa_adds_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_h : GCCBuiltin<"__builtin_msa_adds_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_w : GCCBuiltin<"__builtin_msa_adds_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_d : GCCBuiltin<"__builtin_msa_adds_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addv_b : GCCBuiltin<"__builtin_msa_addv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_h : GCCBuiltin<"__builtin_msa_addv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_w : GCCBuiltin<"__builtin_msa_addv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_d : GCCBuiltin<"__builtin_msa_addv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addvi_b : GCCBuiltin<"__builtin_msa_addvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_h : GCCBuiltin<"__builtin_msa_addvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_w : GCCBuiltin<"__builtin_msa_addvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_d : GCCBuiltin<"__builtin_msa_addvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; + +def int_mips_and_v : GCCBuiltin<"__builtin_msa_and_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_andi_b : GCCBuiltin<"__builtin_msa_andi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_asub_s_b : GCCBuiltin<"__builtin_msa_asub_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_s_h : GCCBuiltin<"__builtin_msa_asub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_s_w : GCCBuiltin<"__builtin_msa_asub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_s_d : GCCBuiltin<"__builtin_msa_asub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_asub_u_b : GCCBuiltin<"__builtin_msa_asub_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_u_h : GCCBuiltin<"__builtin_msa_asub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_u_w : GCCBuiltin<"__builtin_msa_asub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_u_d : GCCBuiltin<"__builtin_msa_asub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ave_s_b : GCCBuiltin<"__builtin_msa_ave_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_h : GCCBuiltin<"__builtin_msa_ave_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_w : GCCBuiltin<"__builtin_msa_ave_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_d : GCCBuiltin<"__builtin_msa_ave_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_ave_u_b : GCCBuiltin<"__builtin_msa_ave_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_h : GCCBuiltin<"__builtin_msa_ave_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_w : GCCBuiltin<"__builtin_msa_ave_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_d : GCCBuiltin<"__builtin_msa_ave_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_s_b : GCCBuiltin<"__builtin_msa_aver_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_h : GCCBuiltin<"__builtin_msa_aver_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_w : GCCBuiltin<"__builtin_msa_aver_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_d : GCCBuiltin<"__builtin_msa_aver_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_u_b : GCCBuiltin<"__builtin_msa_aver_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_h : GCCBuiltin<"__builtin_msa_aver_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_w : GCCBuiltin<"__builtin_msa_aver_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_d : GCCBuiltin<"__builtin_msa_aver_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_bclr_b : GCCBuiltin<"__builtin_msa_bclr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bclr_h : GCCBuiltin<"__builtin_msa_bclr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bclr_w : GCCBuiltin<"__builtin_msa_bclr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bclr_d : GCCBuiltin<"__builtin_msa_bclr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bclri_b : GCCBuiltin<"__builtin_msa_bclri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_h : GCCBuiltin<"__builtin_msa_bclri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_w : GCCBuiltin<"__builtin_msa_bclri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_d : GCCBuiltin<"__builtin_msa_bclri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_binsl_b : GCCBuiltin<"__builtin_msa_binsl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsl_h : GCCBuiltin<"__builtin_msa_binsl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsl_w : GCCBuiltin<"__builtin_msa_binsl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsl_d : GCCBuiltin<"__builtin_msa_binsl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsli_b : GCCBuiltin<"__builtin_msa_binsli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_h : GCCBuiltin<"__builtin_msa_binsli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_w : GCCBuiltin<"__builtin_msa_binsli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_d : GCCBuiltin<"__builtin_msa_binsli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_binsr_b : GCCBuiltin<"__builtin_msa_binsr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsr_h : GCCBuiltin<"__builtin_msa_binsr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsr_w : GCCBuiltin<"__builtin_msa_binsr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsr_d : GCCBuiltin<"__builtin_msa_binsr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsri_b : GCCBuiltin<"__builtin_msa_binsri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_h : GCCBuiltin<"__builtin_msa_binsri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_w : GCCBuiltin<"__builtin_msa_binsri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_d : GCCBuiltin<"__builtin_msa_binsri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmnzi_b : GCCBuiltin<"__builtin_msa_bmnzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmzi_b : GCCBuiltin<"__builtin_msa_bmzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bneg_b : GCCBuiltin<"__builtin_msa_bneg_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bneg_h : GCCBuiltin<"__builtin_msa_bneg_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bneg_w : GCCBuiltin<"__builtin_msa_bneg_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bneg_d : GCCBuiltin<"__builtin_msa_bneg_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnegi_b : GCCBuiltin<"__builtin_msa_bnegi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_h : GCCBuiltin<"__builtin_msa_bnegi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_w : GCCBuiltin<"__builtin_msa_bnegi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_d : GCCBuiltin<"__builtin_msa_bnegi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bnz_b : GCCBuiltin<"__builtin_msa_bnz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bnz_h : GCCBuiltin<"__builtin_msa_bnz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bnz_w : GCCBuiltin<"__builtin_msa_bnz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bnz_d : GCCBuiltin<"__builtin_msa_bnz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnz_v : GCCBuiltin<"__builtin_msa_bnz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_bsel_v : GCCBuiltin<"__builtin_msa_bsel_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bseli_b : GCCBuiltin<"__builtin_msa_bseli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bset_b : GCCBuiltin<"__builtin_msa_bset_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bset_h : GCCBuiltin<"__builtin_msa_bset_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bset_w : GCCBuiltin<"__builtin_msa_bset_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bset_d : GCCBuiltin<"__builtin_msa_bset_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bseti_b : GCCBuiltin<"__builtin_msa_bseti_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_h : GCCBuiltin<"__builtin_msa_bseti_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_w : GCCBuiltin<"__builtin_msa_bseti_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_d : GCCBuiltin<"__builtin_msa_bseti_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bz_b : GCCBuiltin<"__builtin_msa_bz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bz_h : GCCBuiltin<"__builtin_msa_bz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bz_w : GCCBuiltin<"__builtin_msa_bz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bz_d : GCCBuiltin<"__builtin_msa_bz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bz_v : GCCBuiltin<"__builtin_msa_bz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ceq_b : GCCBuiltin<"__builtin_msa_ceq_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ceq_h : GCCBuiltin<"__builtin_msa_ceq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ceq_w : GCCBuiltin<"__builtin_msa_ceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ceq_d : GCCBuiltin<"__builtin_msa_ceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ceqi_b : GCCBuiltin<"__builtin_msa_ceqi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_h : GCCBuiltin<"__builtin_msa_ceqi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_w : GCCBuiltin<"__builtin_msa_ceqi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_d : GCCBuiltin<"__builtin_msa_ceqi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_cfcmsa : GCCBuiltin<"__builtin_msa_cfcmsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_mips_cle_s_b : GCCBuiltin<"__builtin_msa_cle_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_s_h : GCCBuiltin<"__builtin_msa_cle_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_s_w : GCCBuiltin<"__builtin_msa_cle_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_s_d : GCCBuiltin<"__builtin_msa_cle_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_cle_u_b : GCCBuiltin<"__builtin_msa_cle_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_u_h : GCCBuiltin<"__builtin_msa_cle_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_u_w : GCCBuiltin<"__builtin_msa_cle_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_u_d : GCCBuiltin<"__builtin_msa_cle_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clei_s_b : GCCBuiltin<"__builtin_msa_clei_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_h : GCCBuiltin<"__builtin_msa_clei_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_w : GCCBuiltin<"__builtin_msa_clei_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_d : GCCBuiltin<"__builtin_msa_clei_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clei_u_b : GCCBuiltin<"__builtin_msa_clei_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_h : GCCBuiltin<"__builtin_msa_clei_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_w : GCCBuiltin<"__builtin_msa_clei_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_d : GCCBuiltin<"__builtin_msa_clei_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clt_s_b : GCCBuiltin<"__builtin_msa_clt_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_s_h : GCCBuiltin<"__builtin_msa_clt_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_s_w : GCCBuiltin<"__builtin_msa_clt_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_s_d : GCCBuiltin<"__builtin_msa_clt_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clt_u_b : GCCBuiltin<"__builtin_msa_clt_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_u_h : GCCBuiltin<"__builtin_msa_clt_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_u_w : GCCBuiltin<"__builtin_msa_clt_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_u_d : GCCBuiltin<"__builtin_msa_clt_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clti_s_b : GCCBuiltin<"__builtin_msa_clti_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_h : GCCBuiltin<"__builtin_msa_clti_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_w : GCCBuiltin<"__builtin_msa_clti_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_d : GCCBuiltin<"__builtin_msa_clti_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clti_u_b : GCCBuiltin<"__builtin_msa_clti_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_h : GCCBuiltin<"__builtin_msa_clti_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_w : GCCBuiltin<"__builtin_msa_clti_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_d : GCCBuiltin<"__builtin_msa_clti_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_s_b : GCCBuiltin<"__builtin_msa_copy_s_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_h : GCCBuiltin<"__builtin_msa_copy_s_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_w : GCCBuiltin<"__builtin_msa_copy_s_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_d : GCCBuiltin<"__builtin_msa_copy_s_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_u_b : GCCBuiltin<"__builtin_msa_copy_u_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_h : GCCBuiltin<"__builtin_msa_copy_u_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_w : GCCBuiltin<"__builtin_msa_copy_u_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_d : GCCBuiltin<"__builtin_msa_copy_u_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_ctcmsa : GCCBuiltin<"__builtin_msa_ctcmsa">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; + +def int_mips_div_s_b : GCCBuiltin<"__builtin_msa_div_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_s_h : GCCBuiltin<"__builtin_msa_div_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_s_w : GCCBuiltin<"__builtin_msa_div_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_s_d : GCCBuiltin<"__builtin_msa_div_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_div_u_b : GCCBuiltin<"__builtin_msa_div_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_u_h : GCCBuiltin<"__builtin_msa_div_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_u_w : GCCBuiltin<"__builtin_msa_div_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_u_d : GCCBuiltin<"__builtin_msa_div_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_dotp_s_h : GCCBuiltin<"__builtin_msa_dotp_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_s_w : GCCBuiltin<"__builtin_msa_dotp_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_s_d : GCCBuiltin<"__builtin_msa_dotp_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dotp_u_h : GCCBuiltin<"__builtin_msa_dotp_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_u_w : GCCBuiltin<"__builtin_msa_dotp_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_u_d : GCCBuiltin<"__builtin_msa_dotp_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dpadd_s_h : GCCBuiltin<"__builtin_msa_dpadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_w : GCCBuiltin<"__builtin_msa_dpadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_d : GCCBuiltin<"__builtin_msa_dpadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpadd_u_h : GCCBuiltin<"__builtin_msa_dpadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_w : GCCBuiltin<"__builtin_msa_dpadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_d : GCCBuiltin<"__builtin_msa_dpadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_s_h : GCCBuiltin<"__builtin_msa_dpsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_w : GCCBuiltin<"__builtin_msa_dpsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_d : GCCBuiltin<"__builtin_msa_dpsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_u_h : GCCBuiltin<"__builtin_msa_dpsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_w : GCCBuiltin<"__builtin_msa_dpsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_d : GCCBuiltin<"__builtin_msa_dpsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_fadd_w : GCCBuiltin<"__builtin_msa_fadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fadd_d : GCCBuiltin<"__builtin_msa_fadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcaf_w : GCCBuiltin<"__builtin_msa_fcaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcaf_d : GCCBuiltin<"__builtin_msa_fcaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fceq_w : GCCBuiltin<"__builtin_msa_fceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fceq_d : GCCBuiltin<"__builtin_msa_fceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcle_w : GCCBuiltin<"__builtin_msa_fcle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcle_d : GCCBuiltin<"__builtin_msa_fcle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclt_w : GCCBuiltin<"__builtin_msa_fclt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclt_d : GCCBuiltin<"__builtin_msa_fclt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclass_w : GCCBuiltin<"__builtin_msa_fclass_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclass_d : GCCBuiltin<"__builtin_msa_fclass_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcne_w : GCCBuiltin<"__builtin_msa_fcne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcne_d : GCCBuiltin<"__builtin_msa_fcne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcor_w : GCCBuiltin<"__builtin_msa_fcor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcor_d : GCCBuiltin<"__builtin_msa_fcor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcueq_w : GCCBuiltin<"__builtin_msa_fcueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcueq_d : GCCBuiltin<"__builtin_msa_fcueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcule_w : GCCBuiltin<"__builtin_msa_fcule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcule_d : GCCBuiltin<"__builtin_msa_fcule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcult_w : GCCBuiltin<"__builtin_msa_fcult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcult_d : GCCBuiltin<"__builtin_msa_fcult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcun_w : GCCBuiltin<"__builtin_msa_fcun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcun_d : GCCBuiltin<"__builtin_msa_fcun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcune_w : GCCBuiltin<"__builtin_msa_fcune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcune_d : GCCBuiltin<"__builtin_msa_fcune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fdiv_w : GCCBuiltin<"__builtin_msa_fdiv_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fdiv_d : GCCBuiltin<"__builtin_msa_fdiv_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexdo_h : GCCBuiltin<"__builtin_msa_fexdo_h">, + Intrinsic<[llvm_v8f16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fexdo_w : GCCBuiltin<"__builtin_msa_fexdo_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexp2_w : GCCBuiltin<"__builtin_msa_fexp2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_fexp2_d : GCCBuiltin<"__builtin_msa_fexp2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_fexupl_w : GCCBuiltin<"__builtin_msa_fexupl_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupl_d : GCCBuiltin<"__builtin_msa_fexupl_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_fexupr_w : GCCBuiltin<"__builtin_msa_fexupr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupr_d : GCCBuiltin<"__builtin_msa_fexupr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_ffint_s_w : GCCBuiltin<"__builtin_msa_ffint_s_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_s_d : GCCBuiltin<"__builtin_msa_ffint_s_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffint_u_w : GCCBuiltin<"__builtin_msa_ffint_u_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_u_d : GCCBuiltin<"__builtin_msa_ffint_u_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffql_w : GCCBuiltin<"__builtin_msa_ffql_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffql_d : GCCBuiltin<"__builtin_msa_ffql_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ffqr_w : GCCBuiltin<"__builtin_msa_ffqr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffqr_d : GCCBuiltin<"__builtin_msa_ffqr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_fill_b : GCCBuiltin<"__builtin_msa_fill_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_h : GCCBuiltin<"__builtin_msa_fill_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_w : GCCBuiltin<"__builtin_msa_fill_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_d : GCCBuiltin<"__builtin_msa_fill_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; + +def int_mips_flog2_w : GCCBuiltin<"__builtin_msa_flog2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_flog2_d : GCCBuiltin<"__builtin_msa_flog2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmadd_w : GCCBuiltin<"__builtin_msa_fmadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmadd_d : GCCBuiltin<"__builtin_msa_fmadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmax_w : GCCBuiltin<"__builtin_msa_fmax_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_d : GCCBuiltin<"__builtin_msa_fmax_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmax_a_w : GCCBuiltin<"__builtin_msa_fmax_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_a_d : GCCBuiltin<"__builtin_msa_fmax_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_w : GCCBuiltin<"__builtin_msa_fmin_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_d : GCCBuiltin<"__builtin_msa_fmin_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_a_w : GCCBuiltin<"__builtin_msa_fmin_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_a_d : GCCBuiltin<"__builtin_msa_fmin_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmsub_w : GCCBuiltin<"__builtin_msa_fmsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmsub_d : GCCBuiltin<"__builtin_msa_fmsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmul_w : GCCBuiltin<"__builtin_msa_fmul_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmul_d : GCCBuiltin<"__builtin_msa_fmul_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frint_w : GCCBuiltin<"__builtin_msa_frint_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frint_d : GCCBuiltin<"__builtin_msa_frint_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frcp_w : GCCBuiltin<"__builtin_msa_frcp_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frcp_d : GCCBuiltin<"__builtin_msa_frcp_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frsqrt_w : GCCBuiltin<"__builtin_msa_frsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frsqrt_d : GCCBuiltin<"__builtin_msa_frsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsaf_w : GCCBuiltin<"__builtin_msa_fsaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsaf_d : GCCBuiltin<"__builtin_msa_fsaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fseq_w : GCCBuiltin<"__builtin_msa_fseq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fseq_d : GCCBuiltin<"__builtin_msa_fseq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsle_w : GCCBuiltin<"__builtin_msa_fsle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsle_d : GCCBuiltin<"__builtin_msa_fsle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fslt_w : GCCBuiltin<"__builtin_msa_fslt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fslt_d : GCCBuiltin<"__builtin_msa_fslt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsne_w : GCCBuiltin<"__builtin_msa_fsne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsne_d : GCCBuiltin<"__builtin_msa_fsne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsor_w : GCCBuiltin<"__builtin_msa_fsor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsor_d : GCCBuiltin<"__builtin_msa_fsor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsqrt_w : GCCBuiltin<"__builtin_msa_fsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsqrt_d : GCCBuiltin<"__builtin_msa_fsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsub_w : GCCBuiltin<"__builtin_msa_fsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsub_d : GCCBuiltin<"__builtin_msa_fsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsueq_w : GCCBuiltin<"__builtin_msa_fsueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsueq_d : GCCBuiltin<"__builtin_msa_fsueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsule_w : GCCBuiltin<"__builtin_msa_fsule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsule_d : GCCBuiltin<"__builtin_msa_fsule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsult_w : GCCBuiltin<"__builtin_msa_fsult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsult_d : GCCBuiltin<"__builtin_msa_fsult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsun_w : GCCBuiltin<"__builtin_msa_fsun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsun_d : GCCBuiltin<"__builtin_msa_fsun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsune_w : GCCBuiltin<"__builtin_msa_fsune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsune_d : GCCBuiltin<"__builtin_msa_fsune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_s_w : GCCBuiltin<"__builtin_msa_ftint_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_s_d : GCCBuiltin<"__builtin_msa_ftint_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_u_w : GCCBuiltin<"__builtin_msa_ftint_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_u_d : GCCBuiltin<"__builtin_msa_ftint_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftq_h : GCCBuiltin<"__builtin_msa_ftq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftq_w : GCCBuiltin<"__builtin_msa_ftq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_s_w : GCCBuiltin<"__builtin_msa_ftrunc_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_s_d : GCCBuiltin<"__builtin_msa_ftrunc_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_u_w : GCCBuiltin<"__builtin_msa_ftrunc_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_u_d : GCCBuiltin<"__builtin_msa_ftrunc_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_hadd_s_h : GCCBuiltin<"__builtin_msa_hadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_s_w : GCCBuiltin<"__builtin_msa_hadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_s_d : GCCBuiltin<"__builtin_msa_hadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hadd_u_h : GCCBuiltin<"__builtin_msa_hadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_u_w : GCCBuiltin<"__builtin_msa_hadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_u_d : GCCBuiltin<"__builtin_msa_hadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_s_h : GCCBuiltin<"__builtin_msa_hsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_s_w : GCCBuiltin<"__builtin_msa_hsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_s_d : GCCBuiltin<"__builtin_msa_hsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_u_h : GCCBuiltin<"__builtin_msa_hsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_u_w : GCCBuiltin<"__builtin_msa_hsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_u_d : GCCBuiltin<"__builtin_msa_hsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ilvev_b : GCCBuiltin<"__builtin_msa_ilvev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvev_h : GCCBuiltin<"__builtin_msa_ilvev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvev_w : GCCBuiltin<"__builtin_msa_ilvev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvev_d : GCCBuiltin<"__builtin_msa_ilvev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvl_b : GCCBuiltin<"__builtin_msa_ilvl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvl_h : GCCBuiltin<"__builtin_msa_ilvl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvl_w : GCCBuiltin<"__builtin_msa_ilvl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvl_d : GCCBuiltin<"__builtin_msa_ilvl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvod_b : GCCBuiltin<"__builtin_msa_ilvod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvod_h : GCCBuiltin<"__builtin_msa_ilvod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvod_w : GCCBuiltin<"__builtin_msa_ilvod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvod_d : GCCBuiltin<"__builtin_msa_ilvod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvr_b : GCCBuiltin<"__builtin_msa_ilvr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvr_h : GCCBuiltin<"__builtin_msa_ilvr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvr_w : GCCBuiltin<"__builtin_msa_ilvr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvr_d : GCCBuiltin<"__builtin_msa_ilvr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_insert_b : GCCBuiltin<"__builtin_msa_insert_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_h : GCCBuiltin<"__builtin_msa_insert_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_w : GCCBuiltin<"__builtin_msa_insert_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_d : GCCBuiltin<"__builtin_msa_insert_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; + +def int_mips_insve_b : GCCBuiltin<"__builtin_msa_insve_b">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_insve_h : GCCBuiltin<"__builtin_msa_insve_h">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_insve_w : GCCBuiltin<"__builtin_msa_insve_w">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_h : GCCBuiltin<"__builtin_msa_ldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_w : GCCBuiltin<"__builtin_msa_ldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_d : GCCBuiltin<"__builtin_msa_ldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; + +// This instruction is part of the MSA spec but it does not share the +// __builtin_msa prefix because it operates on the GPR registers. +def int_mips_lsa : GCCBuiltin<"__builtin_mips_lsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_madd_q_h : GCCBuiltin<"__builtin_msa_madd_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_madd_q_w : GCCBuiltin<"__builtin_msa_madd_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddr_q_h : GCCBuiltin<"__builtin_msa_maddr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddr_q_w : GCCBuiltin<"__builtin_msa_maddr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddv_b : GCCBuiltin<"__builtin_msa_maddv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_maddv_h : GCCBuiltin<"__builtin_msa_maddv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddv_w : GCCBuiltin<"__builtin_msa_maddv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_maddv_d : GCCBuiltin<"__builtin_msa_maddv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_max_a_b : GCCBuiltin<"__builtin_msa_max_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_a_h : GCCBuiltin<"__builtin_msa_max_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_a_w : GCCBuiltin<"__builtin_msa_max_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_a_d : GCCBuiltin<"__builtin_msa_max_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_s_b : GCCBuiltin<"__builtin_msa_max_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_s_h : GCCBuiltin<"__builtin_msa_max_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_s_w : GCCBuiltin<"__builtin_msa_max_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_s_d : GCCBuiltin<"__builtin_msa_max_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_u_b : GCCBuiltin<"__builtin_msa_max_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_u_h : GCCBuiltin<"__builtin_msa_max_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_u_w : GCCBuiltin<"__builtin_msa_max_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_u_d : GCCBuiltin<"__builtin_msa_max_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_maxi_s_b : GCCBuiltin<"__builtin_msa_maxi_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_h : GCCBuiltin<"__builtin_msa_maxi_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_w : GCCBuiltin<"__builtin_msa_maxi_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_d : GCCBuiltin<"__builtin_msa_maxi_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_maxi_u_b : GCCBuiltin<"__builtin_msa_maxi_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_h : GCCBuiltin<"__builtin_msa_maxi_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_w : GCCBuiltin<"__builtin_msa_maxi_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_d : GCCBuiltin<"__builtin_msa_maxi_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_min_a_b : GCCBuiltin<"__builtin_msa_min_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_a_h : GCCBuiltin<"__builtin_msa_min_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_a_w : GCCBuiltin<"__builtin_msa_min_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_a_d : GCCBuiltin<"__builtin_msa_min_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_s_b : GCCBuiltin<"__builtin_msa_min_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_s_h : GCCBuiltin<"__builtin_msa_min_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_s_w : GCCBuiltin<"__builtin_msa_min_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_s_d : GCCBuiltin<"__builtin_msa_min_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_u_b : GCCBuiltin<"__builtin_msa_min_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_u_h : GCCBuiltin<"__builtin_msa_min_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_u_w : GCCBuiltin<"__builtin_msa_min_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_u_d : GCCBuiltin<"__builtin_msa_min_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mini_s_b : GCCBuiltin<"__builtin_msa_mini_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_h : GCCBuiltin<"__builtin_msa_mini_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_w : GCCBuiltin<"__builtin_msa_mini_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_d : GCCBuiltin<"__builtin_msa_mini_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mini_u_b : GCCBuiltin<"__builtin_msa_mini_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_h : GCCBuiltin<"__builtin_msa_mini_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_w : GCCBuiltin<"__builtin_msa_mini_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_d : GCCBuiltin<"__builtin_msa_mini_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mod_s_b : GCCBuiltin<"__builtin_msa_mod_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_s_h : GCCBuiltin<"__builtin_msa_mod_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_s_w : GCCBuiltin<"__builtin_msa_mod_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_s_d : GCCBuiltin<"__builtin_msa_mod_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mod_u_b : GCCBuiltin<"__builtin_msa_mod_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_u_h : GCCBuiltin<"__builtin_msa_mod_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_u_w : GCCBuiltin<"__builtin_msa_mod_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_u_d : GCCBuiltin<"__builtin_msa_mod_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_move_v : GCCBuiltin<"__builtin_msa_move_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_msub_q_h : GCCBuiltin<"__builtin_msa_msub_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msub_q_w : GCCBuiltin<"__builtin_msa_msub_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubr_q_h : GCCBuiltin<"__builtin_msa_msubr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubr_q_w : GCCBuiltin<"__builtin_msa_msubr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubv_b : GCCBuiltin<"__builtin_msa_msubv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_msubv_h : GCCBuiltin<"__builtin_msa_msubv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubv_w : GCCBuiltin<"__builtin_msa_msubv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_msubv_d : GCCBuiltin<"__builtin_msa_msubv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_mul_q_h : GCCBuiltin<"__builtin_msa_mul_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mul_q_w : GCCBuiltin<"__builtin_msa_mul_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulr_q_h : GCCBuiltin<"__builtin_msa_mulr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulr_q_w : GCCBuiltin<"__builtin_msa_mulr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulv_b : GCCBuiltin<"__builtin_msa_mulv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mulv_h : GCCBuiltin<"__builtin_msa_mulv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulv_w : GCCBuiltin<"__builtin_msa_mulv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mulv_d : GCCBuiltin<"__builtin_msa_mulv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nloc_b : GCCBuiltin<"__builtin_msa_nloc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nloc_h : GCCBuiltin<"__builtin_msa_nloc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nloc_w : GCCBuiltin<"__builtin_msa_nloc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nloc_d : GCCBuiltin<"__builtin_msa_nloc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nlzc_b : GCCBuiltin<"__builtin_msa_nlzc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nlzc_h : GCCBuiltin<"__builtin_msa_nlzc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nlzc_w : GCCBuiltin<"__builtin_msa_nlzc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nlzc_d : GCCBuiltin<"__builtin_msa_nlzc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nor_v : GCCBuiltin<"__builtin_msa_nor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_nori_b : GCCBuiltin<"__builtin_msa_nori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_or_v : GCCBuiltin<"__builtin_msa_or_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ori_b : GCCBuiltin<"__builtin_msa_ori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_pckev_b : GCCBuiltin<"__builtin_msa_pckev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckev_h : GCCBuiltin<"__builtin_msa_pckev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckev_w : GCCBuiltin<"__builtin_msa_pckev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckev_d : GCCBuiltin<"__builtin_msa_pckev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pckod_b : GCCBuiltin<"__builtin_msa_pckod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckod_h : GCCBuiltin<"__builtin_msa_pckod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckod_w : GCCBuiltin<"__builtin_msa_pckod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckod_d : GCCBuiltin<"__builtin_msa_pckod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pcnt_b : GCCBuiltin<"__builtin_msa_pcnt_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pcnt_h : GCCBuiltin<"__builtin_msa_pcnt_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pcnt_w : GCCBuiltin<"__builtin_msa_pcnt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pcnt_d : GCCBuiltin<"__builtin_msa_pcnt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_sat_s_b : GCCBuiltin<"__builtin_msa_sat_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_h : GCCBuiltin<"__builtin_msa_sat_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_w : GCCBuiltin<"__builtin_msa_sat_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_d : GCCBuiltin<"__builtin_msa_sat_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sat_u_b : GCCBuiltin<"__builtin_msa_sat_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_h : GCCBuiltin<"__builtin_msa_sat_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_w : GCCBuiltin<"__builtin_msa_sat_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_d : GCCBuiltin<"__builtin_msa_sat_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_shf_b : GCCBuiltin<"__builtin_msa_shf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_h : GCCBuiltin<"__builtin_msa_shf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_h : GCCBuiltin<"__builtin_msa_sld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_w : GCCBuiltin<"__builtin_msa_sld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sll_h : GCCBuiltin<"__builtin_msa_sll_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sll_w : GCCBuiltin<"__builtin_msa_sll_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sll_d : GCCBuiltin<"__builtin_msa_sll_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_slli_b : GCCBuiltin<"__builtin_msa_slli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_h : GCCBuiltin<"__builtin_msa_slli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_w : GCCBuiltin<"__builtin_msa_slli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_d : GCCBuiltin<"__builtin_msa_slli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splat_b : GCCBuiltin<"__builtin_msa_splat_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_h : GCCBuiltin<"__builtin_msa_splat_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_w : GCCBuiltin<"__builtin_msa_splat_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_d : GCCBuiltin<"__builtin_msa_splat_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splati_b : GCCBuiltin<"__builtin_msa_splati_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_h : GCCBuiltin<"__builtin_msa_splati_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_w : GCCBuiltin<"__builtin_msa_splati_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_d : GCCBuiltin<"__builtin_msa_splati_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sra_b : GCCBuiltin<"__builtin_msa_sra_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sra_h : GCCBuiltin<"__builtin_msa_sra_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sra_w : GCCBuiltin<"__builtin_msa_sra_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sra_d : GCCBuiltin<"__builtin_msa_sra_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srai_b : GCCBuiltin<"__builtin_msa_srai_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_h : GCCBuiltin<"__builtin_msa_srai_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_w : GCCBuiltin<"__builtin_msa_srai_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_d : GCCBuiltin<"__builtin_msa_srai_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srar_b : GCCBuiltin<"__builtin_msa_srar_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srar_h : GCCBuiltin<"__builtin_msa_srar_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srar_w : GCCBuiltin<"__builtin_msa_srar_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srar_d : GCCBuiltin<"__builtin_msa_srar_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srari_b : GCCBuiltin<"__builtin_msa_srari_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_h : GCCBuiltin<"__builtin_msa_srari_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_w : GCCBuiltin<"__builtin_msa_srari_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_d : GCCBuiltin<"__builtin_msa_srari_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srl_b : GCCBuiltin<"__builtin_msa_srl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srl_h : GCCBuiltin<"__builtin_msa_srl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srl_w : GCCBuiltin<"__builtin_msa_srl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srl_d : GCCBuiltin<"__builtin_msa_srl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srli_b : GCCBuiltin<"__builtin_msa_srli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_h : GCCBuiltin<"__builtin_msa_srli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_w : GCCBuiltin<"__builtin_msa_srli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_d : GCCBuiltin<"__builtin_msa_srli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srlr_b : GCCBuiltin<"__builtin_msa_srlr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srlr_h : GCCBuiltin<"__builtin_msa_srlr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srlr_w : GCCBuiltin<"__builtin_msa_srlr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srlr_d : GCCBuiltin<"__builtin_msa_srlr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srlri_b : GCCBuiltin<"__builtin_msa_srlri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_h : GCCBuiltin<"__builtin_msa_srlri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_w : GCCBuiltin<"__builtin_msa_srlri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">, + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">, + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">, + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">, + Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_s_h : GCCBuiltin<"__builtin_msa_subs_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_s_w : GCCBuiltin<"__builtin_msa_subs_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_s_d : GCCBuiltin<"__builtin_msa_subs_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subs_u_b : GCCBuiltin<"__builtin_msa_subs_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_u_h : GCCBuiltin<"__builtin_msa_subs_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_u_w : GCCBuiltin<"__builtin_msa_subs_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_u_d : GCCBuiltin<"__builtin_msa_subs_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsus_u_b : GCCBuiltin<"__builtin_msa_subsus_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsus_u_h : GCCBuiltin<"__builtin_msa_subsus_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsus_u_w : GCCBuiltin<"__builtin_msa_subsus_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsus_u_d : GCCBuiltin<"__builtin_msa_subsus_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsuu_s_b : GCCBuiltin<"__builtin_msa_subsuu_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsuu_s_h : GCCBuiltin<"__builtin_msa_subsuu_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsuu_s_w : GCCBuiltin<"__builtin_msa_subsuu_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsuu_s_d : GCCBuiltin<"__builtin_msa_subsuu_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subv_b : GCCBuiltin<"__builtin_msa_subv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subv_h : GCCBuiltin<"__builtin_msa_subv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subv_w : GCCBuiltin<"__builtin_msa_subv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subv_d : GCCBuiltin<"__builtin_msa_subv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subvi_b : GCCBuiltin<"__builtin_msa_subvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_h : GCCBuiltin<"__builtin_msa_subvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_w : GCCBuiltin<"__builtin_msa_subvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_d : GCCBuiltin<"__builtin_msa_subvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_vshf_b : GCCBuiltin<"__builtin_msa_vshf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_vshf_h : GCCBuiltin<"__builtin_msa_vshf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_vshf_w : GCCBuiltin<"__builtin_msa_vshf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_vshf_d : GCCBuiltin<"__builtin_msa_vshf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_xor_v : GCCBuiltin<"__builtin_msa_xor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_xori_b : GCCBuiltin<"__builtin_msa_xori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; } diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index c248517def6f3..a372c22e43477 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -861,8 +861,6 @@ def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], // Move intrinsics, used in nvvm internally -def int_nvvm_move_i8 : Intrinsic<[llvm_i8_ty], [llvm_i8_ty], [IntrNoMem], - "llvm.nvvm.move.i8">; def int_nvvm_move_i16 : Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem], "llvm.nvvm.move.i16">; def int_nvvm_move_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem], diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5664f79250272..49ddfb8b613b2 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -30,6 +30,11 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // sync instruction def int_ppc_sync : Intrinsic<[], [], []>; + + // Intrinsics used to generate ctr-based loops. These should only be + // generated by the PowerPC backend! + def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; + def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; } diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 69e0ab4fa2ed9..4c5718f8c8b5d 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -206,6 +206,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". 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">, @@ -936,9 +937,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_crc32_32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse42_crc32_64_8 : - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse42_crc32_64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; @@ -1635,7 +1633,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_avx2_vbroadcasti128 : - GCCBuiltin<"__builtin_ia32_vbroadcastsi256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, @@ -1867,6 +1864,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1891,6 +1896,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1915,6 +1928,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1939,6 +1960,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1957,6 +1986,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -1975,6 +2012,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -2549,6 +2594,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } +//===----------------------------------------------------------------------===// +// TBM + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_tbm_bextri_u32 : GCCBuiltin<"__builtin_ia32_bextri_u32">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_tbm_bextri_u64 : GCCBuiltin<"__builtin_ia32_bextri_u64">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} + //===----------------------------------------------------------------------===// // RDRAND intrinsics - Return a random value and whether it is valid. // RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and @@ -2578,3 +2633,493 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, Intrinsic<[llvm_i32_ty], [], []>; } + +//===----------------------------------------------------------------------===// +// AVX512 + +// Mask ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Mask instructions + // 16-bit mask + def int_x86_kadd_v16i1 : GCCBuiltin<"__builtin_ia32_kaddw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kand_v16i1 : GCCBuiltin<"__builtin_ia32_kandw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kandn_v16i1 : GCCBuiltin<"__builtin_ia32_kandnw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_knot_v16i1 : GCCBuiltin<"__builtin_ia32_knotw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_kor_v16i1 : GCCBuiltin<"__builtin_ia32_korw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxor_v16i1 : GCCBuiltin<"__builtin_ia32_kxorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxnor_v16i1 : GCCBuiltin<"__builtin_ia32_kxnorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_mask2int_v16i1 : GCCBuiltin<"__builtin_ia32_mask2intw">, + Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_int2mask_v16i1 : GCCBuiltin<"__builtin_ia32_int2maskw">, + Intrinsic<[llvm_v16i1_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_x86_kunpck_v16i1 : GCCBuiltin<"__builtin_ia32_kunpckbw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v8i1_ty, llvm_v8i1_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestz : GCCBuiltin<"__builtin_ia32_kortestz">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestc : GCCBuiltin<"__builtin_ia32_kortestc">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvtss2usi : GCCBuiltin<"__builtin_ia32_cvtss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtss2usi64 : GCCBuiltin<"__builtin_ia32_cvtss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi : GCCBuiltin<"__builtin_ia32_cvttss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_cvttss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_cvtsd2usi : GCCBuiltin<"__builtin_ia32_cvtsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtsd2usi64 : GCCBuiltin<"__builtin_ia32_cvtsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi : GCCBuiltin<"__builtin_ia32_cvttsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_cvttsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx512_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector convert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvt_ps2dq_512 : GCCBuiltin<"__builtin_ia32_cvtps2dq512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtdq2_ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty], [IntrNoMem]>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_vbroadcast_ss_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss512">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_ss_ps_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss_ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + def int_x86_avx512_vbroadcast_sd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_sd_pd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd_pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastd_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastd_i32_512 : + Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastq_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastq_i64_512 : + Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], + [IntrNoMem]>; +} + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxu_q : GCCBuiltin<"__builtin_ia32_pmaxuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_q : GCCBuiltin<"__builtin_ia32_pmaxsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + + def int_x86_avx512_pminu_d : GCCBuiltin<"__builtin_ia32_pminud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pminu_q : GCCBuiltin<"__builtin_ia32_pminuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_q : GCCBuiltin<"__builtin_ia32_pminsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + + def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtrndsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + + def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rcp28_ps_512 : GCCBuiltin<"__builtin_ia32_rcp28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_pd_512 : GCCBuiltin<"__builtin_ia32_rcp28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Gather and Scatter ops +let TargetPrefix = "x86" in { + def int_x86_avx512_gather_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; +// scatter + def int_x86_avx512_scatter_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_v16f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, + llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i32_ty, + llvm_i32_ty], + []>; +} + +// AVX-512 conflict detection +let TargetPrefix = "x86" in { + def int_x86_avx512_conflict_d_512 : GCCBuiltin<"__builtin_ia32_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i1_ty, llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i1_ty, llvm_v16i32_ty], + []>; + + def int_x86_avx512_conflict_q_512 : GCCBuiltin<"__builtin_ia32_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i1_ty, llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i1_ty, llvm_v8i64_ty], + []>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mskblend_ps_512 : GCCBuiltin<"__builtin_ia32_mskblendps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i1_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_pd_512 : GCCBuiltin<"__builtin_ia32_mskblendpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i1_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mskblend_d_512 : GCCBuiltin<"__builtin_ia32_mskblendd512">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_q_512 : GCCBuiltin<"__builtin_ia32_mskblendq512">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i64_ty], + [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { + def int_x86_avx512_cmpeq_pi_512 : GCCBuiltin<"__builtin_ia32_cmpeqpi512">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_and_pi : GCCBuiltin<"__builtin_ia32_andpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SHA intrinsics +let TargetPrefix = "x86" in { + def int_x86_sha1rnds4 : GCCBuiltin<"__builtin_ia32_sha1rnds4">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sha1nexte : GCCBuiltin<"__builtin_ia32_sha1nexte">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg1 : GCCBuiltin<"__builtin_ia32_sha1msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg2 : GCCBuiltin<"__builtin_ia32_sha1msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256rnds2 : GCCBuiltin<"__builtin_ia32_sha256rnds2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sha256msg1 : GCCBuiltin<"__builtin_ia32_sha256msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td index a4813135da8d1..bf345d4d00c07 100644 --- a/include/llvm/IR/IntrinsicsXCore.td +++ b/include/llvm/IR/IntrinsicsXCore.td @@ -13,7 +13,8 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". // Miscellaneous instructions. - def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>, + GCCBuiltin<"__builtin_bitrev">; def int_xcore_crc8 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], [IntrNoMem]>; @@ -24,9 +25,12 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [IntrNoMem]>; def int_xcore_zext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; - def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>; - def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>, + GCCBuiltin<"__builtin_getid">; + def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>, + GCCBuiltin<"__builtin_getps">; + def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>, + GCCBuiltin<"__builtin_setps">; def int_xcore_geted : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index f25d820c2bb99..dd379ae5e72c9 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -30,7 +30,7 @@ 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 +/// (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. @@ -39,7 +39,7 @@ 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 { @@ -51,19 +51,19 @@ public: MD_tbaa_struct = 5, // "tbaa.struct" MD_invariant_load = 6 // "invariant.load" }; - + /// 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 @@ -81,8 +81,8 @@ public: /// 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". @@ -99,10 +99,10 @@ private: /// 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; }; diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h new file mode 100644 index 0000000000000..fa1436ec63247 --- /dev/null +++ b/include/llvm/IR/LegacyPassManager.h @@ -0,0 +1,111 @@ +//===- LegacyPassManager.h - Legacy 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 legacy 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_IR_LEGACYPASSMANAGER_H +#define LLVM_IR_LEGACYPASSMANAGER_H + +#include "llvm/Pass.h" +#include "llvm/Support/CBindingWrapping.h" + +namespace llvm { + +class Pass; +class Module; + +namespace legacy { + +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: + /// 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. + /// 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: + FunctionPassManagerImpl *FPM; + Module *M; +}; + +} // End legacy namespace + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_STDCXX_CONVERSION_FUNCTIONS(legacy::PassManagerBase, LLVMPassManagerRef) + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h new file mode 100644 index 0000000000000..d256a3e92ccf7 --- /dev/null +++ b/include/llvm/IR/LegacyPassManagers.h @@ -0,0 +1,470 @@ +//===- LegacyPassManagers.h - Legacy Pass Infrastructure --------*- 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/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Pass.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 PMTopLevelManager +// +// 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); + + unsigned getNumContainedManagers() const { + return (unsigned)PassManagers.size(); + } + + void initializeAllAnalysisInfo(); + +private: + virtual PMDataManager *getAsPMDataManager() = 0; + virtual PassManagerType getTopLevelPassManagerType() = 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(ArrayRef 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() : TPM(NULL), Depth(0) { + 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; } + void setDepth(unsigned newDepth) { Depth = newDepth; } + + // 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; + + unsigned getNumContainedPasses() const { + return (unsigned)PassVector.size(); + } + + virtual PassManagerType getPassManagerType() const { + assert ( 0 && "Invalid use of getPassManagerType"); + return PMT_Unknown; + } + + DenseMap *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. + DenseMap *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. + DenseMap 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() + : ModulePass(ID), PMDataManager() { } + + /// 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 - Overrides ModulePass doInitialization for global + /// initialization tasks + /// + using ModulePass::doInitialization; + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(Module &M); + + /// doFinalization - Overrides ModulePass doFinalization for global + /// finalization tasks + /// + using ModulePass::doFinalization; + + /// 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/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 8c2cfac235d2d..9659c2e05c382 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -22,15 +22,16 @@ #include "llvm/IR/Value.h" namespace llvm { -class Constant; -class Instruction; class LLVMContext; class Module; -template class SmallVectorImpl; template class SymbolTableListTraits; +enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { + DEBUG_METADATA_VERSION = 1 // Current debug info version number. +}; + //===----------------------------------------------------------------------===// /// MDString - a single uniqued string. /// These are used to efficiently contain a byte sequence for metadata. @@ -139,7 +140,7 @@ public: void replaceOperandWith(unsigned i, Value *NewVal); /// getOperand - Return specified operand. - Value *getOperand(unsigned i) const; + Value *getOperand(unsigned i) const LLVM_READONLY; /// getNumOperands - Return number of MDNode operands. unsigned getNumOperands() const { return NumOperands; } @@ -164,6 +165,9 @@ public: return V->getValueID() == MDNodeVal; } + /// Check whether MDNode is a vtable access. + bool isTBAAVtableAccess() const; + /// Methods for metadata merging. static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index cb500ffe7cb6a..b30a9a3d1abf2 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -340,10 +340,6 @@ public: Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) END_WITH_NULL; - Constant *getOrInsertTargetIntrinsic(StringRef Name, - FunctionType *Ty, - AttributeSet AttributeList); - /// getFunction - Look up the specified function in the module symbol table. /// If it does not exist, return null. Function *getFunction(StringRef Name) const; @@ -356,15 +352,22 @@ public: /// 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; + const GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const { + return const_cast(this)->getGlobalVariable(Name, AllowInternal); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false); /// getNamedGlobal - Return the global variable in the module with the /// specified name, of arbitrary type. This method returns null if a global /// with the specified name is not found. - GlobalVariable *getNamedGlobal(StringRef Name) const { + GlobalVariable *getNamedGlobal(StringRef Name) { return getGlobalVariable(Name, true); } + const GlobalVariable *getNamedGlobal(StringRef Name) const { + return const_cast(this)->getNamedGlobal(Name); + } /// getOrInsertGlobal - Look up the specified global in the module symbol /// table. @@ -388,7 +391,7 @@ public: /// @name Named Metadata Accessors /// @{ - /// getNamedMetadata - Return the NamedMDNode in the module with the + /// 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; @@ -409,6 +412,10 @@ public: /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void getModuleFlagsMetadata(SmallVectorImpl &Flags) const; + /// Return the corresponding value if Key appears in module flags, otherwise + /// return null. + Value *getModuleFlag(StringRef Key) const; + /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that /// represents module-level flags. This method returns null if there are no /// module-level flags. diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 13ab72cfefc85..5b9bee7fc60f0 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -439,8 +439,8 @@ public: /// offset of this GEP if the GEP is in fact constant. If the GEP is not /// all-constant, it returns false and the value of the offset APInt is /// undefined (it is *not* preserved!). The APInt passed into this routine - /// must be at least as wide as the IntPtr type for the address space of - /// the base GEP pointer. + /// must be at exactly as wide as the IntPtr type for the address space of the + /// base GEP pointer. bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { assert(Offset.getBitWidth() == DL.getPointerSizeInBits(getPointerAddressSpace()) && diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h new file mode 100644 index 0000000000000..833547a23acc6 --- /dev/null +++ b/include/llvm/IR/PassManager.h @@ -0,0 +1,383 @@ +//===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines various interfaces for pass management in LLVM. There +/// is no "pass" interface in LLVM per se. Instead, an instance of any class +/// which supports a method to 'run' it over a unit of IR can be used as +/// a pass. A pass manager is generally a tool to collect a sequence of passes +/// which run over a particular IR construct, and run each of them in sequence +/// over each such construct in the containing IR construct. As there is no +/// containing IR construct for a Module, a manager for passes over modules +/// forms the base case which runs its managed passes in sequence over the +/// single module provided. +/// +/// The core IR library provides managers for running passes over +/// modules and functions. +/// +/// * FunctionPassManager can run over a Module, runs each pass over +/// a Function. +/// * ModulePassManager must be directly run, runs each pass over the Module. +/// +/// Note that the implementations of the pass managers use concept-based +/// polymorphism as outlined in the "Value Semantics and Concept-based +/// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base +/// Class of Evil") by Sean Parent: +/// * http://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations +/// * http://www.youtube.com/watch?v=_BpMYeUFXv8 +/// * http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/polymorphic_ptr.h" +#include "llvm/Support/type_traits.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include +#include + +namespace llvm { + +class Module; +class Function; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + virtual PassConcept *clone() = 0; + + /// \brief The polymorphic API which runs the pass over a given IR entity. + virtual bool run(T Arg) = 0; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method +/// accepting a \c T. It requires the pass to be a copyable +/// object. +template struct PassModel : PassConcept { + PassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual PassModel *clone() { return new PassModel(Pass); } + virtual bool run(T Arg) { return Pass.run(Arg); } + PassT Pass; +}; + +} + +class AnalysisManager; + +class ModulePassManager { +public: + ModulePassManager(Module *M, AnalysisManager *AM = 0) : M(M), AM(AM) {} + + template void addPass(ModulePassT Pass) { + Passes.push_back(new ModulePassModel(llvm_move(Pass))); + } + + void run(); + +private: + // Pull in the concept type and model template specialized for modules. + typedef detail::PassConcept ModulePassConcept; + template + struct ModulePassModel : detail::PassModel { + ModulePassModel(PassT Pass) : detail::PassModel(Pass) {} + }; + + Module *M; + AnalysisManager *AM; + std::vector > Passes; +}; + +class FunctionPassManager { +public: + FunctionPassManager(AnalysisManager *AM = 0) : AM(AM) {} + + template void addPass(FunctionPassT Pass) { + Passes.push_back(new FunctionPassModel(llvm_move(Pass))); + } + + bool run(Module *M); + +private: + // Pull in the concept type and model template specialized for functions. + typedef detail::PassConcept FunctionPassConcept; + template + struct FunctionPassModel : detail::PassModel { + FunctionPassModel(PassT Pass) + : detail::PassModel(Pass) {} + }; + + AnalysisManager *AM; + std::vector > Passes; +}; + + +/// \brief An analysis manager to coordinate and cache analyses run over +/// a module. +/// +/// The analysis manager is typically used by passes in a pass pipeline +/// (consisting potentially of several individual pass managers) over a module +/// of IR. It provides registration of available analyses, declaring +/// requirements on support for specific analyses, running of an specific +/// analysis over a specific unit of IR to compute an analysis result, and +/// caching of the analysis results to reuse them across multiple passes. +/// +/// It is the responsibility of callers to use the invalidation API to +/// invalidate analysis results when the IR they correspond to changes. The +/// \c ModulePassManager and \c FunctionPassManager do this automatically. +class AnalysisManager { +public: + AnalysisManager(Module *M) : M(M) {} + + /// \brief Get the result of an analysis pass for this module. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + /// + /// The module passed in must be the same module as the analysis manager was + /// constructed around. + template + const typename PassT::Result &getResult(Module *M) { + assert(ModuleAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept &ResultConcept = + getResultImpl(PassT::ID(), M); + typedef AnalysisResultModel ResultModelT; + return static_cast(ResultConcept).Result; + } + + /// \brief Get the result of an analysis pass for a function. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + template + const typename PassT::Result &getResult(Function *F) { + assert(FunctionAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept &ResultConcept = + getResultImpl(PassT::ID(), F); + typedef AnalysisResultModel ResultModelT; + return static_cast(ResultConcept).Result; + } + + /// \brief Register an analysis pass with the manager. + /// + /// This provides an initialized and set-up analysis pass to the + /// analysis + /// manager. Whomever is setting up analysis passes must use this to + /// populate + /// the manager with all of the analysis passes available. + template void registerAnalysisPass(PassT Pass) { + registerAnalysisPassImpl(llvm_move(Pass)); + } + + /// \brief Invalidate a specific analysis pass for an IR module. + /// + /// Note that the analysis result can disregard invalidation. + template void invalidate(Module *M) { + invalidateImpl(PassT::ID(), M); + } + + /// \brief Invalidate a specific analysis pass for an IR function. + /// + /// Note that the analysis result can disregard invalidation. + template void invalidate(Function *F) { + invalidateImpl(PassT::ID(), F); + } + + /// \brief Invalidate analyses cached for an IR Module. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding their invalidate method. + /// + /// The module must be the module this analysis manager was constructed + /// around. + void invalidateAll(Module *M); + + /// \brief Invalidate analyses cached for an IR Function. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding the invalidate method. + void invalidateAll(Function *F); + +private: + /// \brief Abstract concept of an analysis result. + /// + /// This concept is parameterized over the IR unit that this result pertains + /// to. + template struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + virtual AnalysisResultConcept *clone() = 0; + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer \c AnalysisManager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// \returns true if the result should indeed be invalidated (the default). + virtual bool invalidate(IRUnitT *IR) = 0; + }; + + /// \brief Wrapper to model the analysis result concept. + /// + /// Can wrap any type which implements a suitable invalidate member and model + /// the AnalysisResultConcept for the AnalysisManager. + template + struct AnalysisResultModel : AnalysisResultConcept { + AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {} + virtual AnalysisResultModel *clone() { + return new AnalysisResultModel(Result); + } + + /// \brief The model delegates to the \c ResultT method. + virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); } + + ResultT Result; + }; + + /// \brief Abstract concept of an analysis pass. + /// + /// This concept is parameterized over the IR unit that it can run over and + /// produce an analysis result. + template struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + virtual AnalysisPassConcept *clone() = 0; + + /// \brief Method to run this analysis over a unit of IR. + /// \returns The analysis result object to be queried by users, the caller + /// takes ownership. + virtual AnalysisResultConcept *run(IRUnitT *IR) = 0; + }; + + /// \brief Wrapper to model the analysis pass concept. + /// + /// Can wrap any type which implements a suitable \c run method. The method + /// must accept the IRUnitT as an argument and produce an object which can be + /// wrapped in a \c AnalysisResultModel. + template + struct AnalysisPassModel : AnalysisPassConcept { + AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } + + // FIXME: Replace PassT::IRUnitT with type traits when we use C++11. + typedef typename PassT::IRUnitT IRUnitT; + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + virtual ResultModelT *run(IRUnitT *IR) { + return new ResultModelT(Pass.run(IR)); + } + + PassT Pass; + }; + + + /// \brief Get a module pass result, running the pass if necessary. + const AnalysisResultConcept &getResultImpl(void *PassID, Module *M); + + /// \brief Get a function pass result, running the pass if necessary. + const AnalysisResultConcept &getResultImpl(void *PassID, + Function *F); + + /// \brief Invalidate a module pass result. + void invalidateImpl(void *PassID, Module *M); + + /// \brief Invalidate a function pass result. + void invalidateImpl(void *PassID, Function *F); + + + /// \brief Module pass specific implementation of registration. + template + typename enable_if >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!ModuleAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + ModuleAnalysisPasses[PassT::ID()] = + new AnalysisPassModel(llvm_move(Pass)); + } + + /// \brief Function pass specific implementation of registration. + template + typename enable_if >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!FunctionAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + FunctionAnalysisPasses[PassT::ID()] = + new AnalysisPassModel(llvm_move(Pass)); + } + + + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap > > + ModuleAnalysisPassMapT; + + /// \brief Collection of module analysis passes, indexed by ID. + ModuleAnalysisPassMapT ModuleAnalysisPasses; + + /// \brief Map type from module analysis pass ID to pass result concept pointer. + typedef DenseMap > > + ModuleAnalysisResultMapT; + + /// \brief Cache of computed module analysis results for this module. + ModuleAnalysisResultMapT ModuleAnalysisResults; + + + /// \brief Map type from function analysis pass ID to pass concept pointer. + typedef DenseMap > > + FunctionAnalysisPassMapT; + + /// \brief Collection of function analysis passes, indexed by ID. + FunctionAnalysisPassMapT FunctionAnalysisPasses; + + /// \brief List of function analysis pass IDs and associated concept pointers. + /// + /// Requires iterators to be valid across appending new entries and arbitrary + /// erases. Provides both the pass ID and concept pointer such that it is + /// half of a bijection and provides storage for the actual result concept. + typedef std::list< + std::pair > > > + FunctionAnalysisResultListT; + + /// \brief Map type from function pointer to our custom list type. + typedef DenseMap FunctionAnalysisResultListMapT; + + /// \brief Map from function to a list of function analysis results. + /// + /// Provides linear time removal of all analysis results for a function and + /// the ultimate storage for a particular cached analysis result. + FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + + /// \brief Map type from a pair of analysis ID and function pointer to an + /// iterator into a particular result list. + typedef DenseMap, + FunctionAnalysisResultListT::iterator> + FunctionAnalysisResultMapT; + + /// \brief Map from an analysis ID and function to a particular cached + /// analysis result. + FunctionAnalysisResultMapT FunctionAnalysisResults; + + /// \brief Module handle for the \c AnalysisManager. + Module *M; +}; + +} diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 1bf8789d30724..3cfb84edd824c 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -324,6 +324,14 @@ public: subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + typedef std::reverse_iterator subtype_reverse_iterator; + subtype_reverse_iterator subtype_rbegin() const { + return subtype_reverse_iterator(subtype_end()); + } + subtype_reverse_iterator subtype_rend() const { + return subtype_reverse_iterator(subtype_begin()); + } + /// 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. diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 80c60a0806141..5a29e1e10855e 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -17,7 +17,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" -#include +#include namespace llvm { diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index efd8b48a0e9be..12cd150af4c88 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -177,7 +177,6 @@ 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 { diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 5fba3d5714423..e1361fef351e9 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -22,26 +22,29 @@ namespace llvm { -class Constant; +class APInt; class Argument; -class Instruction; +class AssemblyAnnotationWriter; class BasicBlock; -class GlobalValue; +class Constant; +class DataLayout; class Function; -class GlobalVariable; class GlobalAlias; +class GlobalValue; +class GlobalVariable; class InlineAsm; -class ValueSymbolTable; -template class StringMapEntry; -typedef StringMapEntry ValueName; -class raw_ostream; -class AssemblyAnnotationWriter; -class ValueHandleBase; +class Instruction; class LLVMContext; -class Twine; class MDNode; -class Type; class StringRef; +class Twine; +class Type; +class ValueHandleBase; +class ValueSymbolTable; +class raw_ostream; + +template class StringMapEntry; +typedef StringMapEntry ValueName; //===----------------------------------------------------------------------===// // Value Class @@ -260,37 +263,53 @@ public: /// this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief This method strips off any unneeded pointer casts, - /// all-zero GEPs and aliases from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases + /// from the specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCasts(); const Value *stripPointerCasts() const { return const_cast(this)->stripPointerCasts(); } - /// \brief This method strips off any unneeded pointer casts and - /// all-zero GEPs from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the + /// specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCastsNoFollowAliases(); const Value *stripPointerCastsNoFollowAliases() const { return const_cast(this)->stripPointerCastsNoFollowAliases(); } - /// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and - /// all-constant GEPs from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off unneeded pointer casts and all-constant GEPs from the + /// specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsConstantOffsets(); const Value *stripInBoundsConstantOffsets() const { return const_cast(this)->stripInBoundsConstantOffsets(); } - /// stripInBoundsOffsets - This method strips off unneeded pointer casts and - /// any in-bounds Offsets from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates + /// the constant offset stripped. + /// + /// Stores the resulting constant offset stripped into the APInt provided. + /// The provided APInt will be extended or truncated as needed to be the + /// correct bitwidth for an offset of this pointer type. + /// + /// If this is called on a non-pointer value, it returns 'this'. + Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset); + const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset) const { + return const_cast(this) + ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + } + + /// \brief Strips off unneeded pointer casts and any in-bounds offsets from + /// the specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsOffsets(); const Value *stripInBoundsOffsets() const { return const_cast(this)->stripInBoundsOffsets(); diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 5b2cd603c3f98..aefb3c065b8f7 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -70,13 +70,13 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); +void initializeSampleProfileLoaderPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); -void initializeBasicCallGraphPass(PassRegistry&); +void initializeCallGraphPass(PassRegistry&); void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); -void initializeBlockPlacementPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); @@ -87,9 +87,9 @@ void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeFlattenCFGPassPass(PassRegistry&); +void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); -void initializeCalculateSpillWeightsPass(PassRegistry&); -void initializeCallGraphAnalysisGroup(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); @@ -100,8 +100,10 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); +void initializeDebugIRPass(PassRegistry&); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); @@ -111,14 +113,13 @@ void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreePass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); -void initializeEdgeProfilerPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); -void initializePathProfilerPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); +void initializeDataFlowSanitizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); @@ -152,8 +153,6 @@ void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); -void initializeProfileMetadataLoaderPassPass(PassRegistry&); -void initializePathProfileLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); @@ -163,6 +162,7 @@ void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); +void initializeLoopRerollPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); @@ -192,15 +192,13 @@ void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeNoAAPass(PassRegistry&); -void initializeNoProfileInfoPass(PassRegistry&); -void initializeNoPathProfileInfoPass(PassRegistry&); void initializeObjCARCAliasAnalysisPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); -void initializeOptimalEdgeProfilerPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); +void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); void initializePartialInlinerPass(PassRegistry&); @@ -216,11 +214,6 @@ void initializePrintFunctionPassPass(PassRegistry&); void initializePrintModulePassPass(PassRegistry&); void initializePrintBasicBlockPassPass(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 initializeReassociatePass(PassRegistry&); @@ -238,7 +231,6 @@ void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); -void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); void initializeSlotIndexesPass(PassRegistry&); @@ -251,7 +243,6 @@ void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); -void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); diff --git a/include/llvm/InstVisitor.h b/include/llvm/InstVisitor.h index 291170334c0a3..de7206da6b5f3 100644 --- a/include/llvm/InstVisitor.h +++ b/include/llvm/InstVisitor.h @@ -191,6 +191,7 @@ public: RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);} RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);} RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);} + RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);} RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);} RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);} RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h new file mode 100644 index 0000000000000..c478bd980d4f6 --- /dev/null +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -0,0 +1,153 @@ +//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// +// +// 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 LTOCodeGenerator class. +// +// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. +// +// The Pre-IPO phase compiles source code into bitcode file. The resulting +// bitcode files, along with object files and libraries, will be fed to the +// linker to through the IPO and Post-IPO phases. By using obj-file extension, +// the resulting bitcode file disguises itself as an object file, and therefore +// obviates the need of writing a special set of the make-rules only for LTO +// compilation. +// +// The IPO phase perform inter-procedural analyses and optimizations, and +// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations +// (SOPT), and intra-procedural target-dependent code generator (CG). +// +// As of this writing, we don't separate IPO and the Post-IPO SOPT. They +// are intermingled together, and are driven by a single pass manager (see +// PassManagerBuilder::populateLTOPassManager()). +// +// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. +// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" +// with the machine specific code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_CODE_GENERATOR_H +#define LTO_CODE_GENERATOR_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Linker.h" +#include "llvm/Target/TargetOptions.h" +#include +#include + +namespace llvm { + class LLVMContext; + class GlobalValue; + class Mangler; + class MemoryBuffer; + class TargetLibraryInfo; + class TargetMachine; + class raw_ostream; +} + +//===----------------------------------------------------------------------===// +/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t +/// type. +/// +struct LTOCodeGenerator { + static const char *getVersionString(); + + LTOCodeGenerator(); + ~LTOCodeGenerator(); + + // Merge given module, return true on success. + bool addModule(struct LTOModule*, std::string &errMsg); + + void setTargetOptions(llvm::TargetOptions options); + void setDebugInfo(lto_debug_model); + void setCodePICModel(lto_codegen_model); + + void setCpu(const char *mCpu) { MCpu = mCpu; } + + void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } + + // To pass options to the driver and optimization passes. These options are + // not necessarily for debugging purpose (The function name is misleading). + // This function should be called before LTOCodeGenerator::compilexxx(), + // and LTOCodeGenerator::writeMergedModules(). + // + void setCodeGenDebugOptions(const char *opts); + + // Parse the options set in setCodeGenDebugOptions. Like + // setCodeGenDebugOptions, this must be called before + // LTOCodeGenerator::compilexxx() and LTOCodeGenerator::writeMergedModules() + void parseCodeGenDebugOptions(); + + // Write the merged module to the file specified by the given path. + // Return true on success. + bool writeMergedModules(const char *path, std::string &errMsg); + + // Compile the merged module into a *single* object file; the path to object + // file is returned to the caller via argument "name". Return true on + // success. + // + // NOTE that it is up to the linker to remove the intermediate object file. + // Do not try to remove the object file in LTOCodeGenerator's destructor + // as we don't who (LTOCodeGenerator or the obj file) will last longer. + // + bool compile_to_file(const char **name, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + + // As with compile_to_file(), this function compiles the merged module into + // single object file. Instead of returning the object-file-path to the caller + // (linker), it brings the object to a buffer, and return the buffer to the + // caller. This function should delete intermediate object file once its content + // is brought to memory. Return NULL if the compilation was not successful. + // + const void *compile(size_t *length, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + +private: + void initializeLTOPasses(); + + bool generateObjectFile(llvm::raw_ostream &out, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + void applyScopeRestrictions(); + void applyRestriction(llvm::GlobalValue &GV, + const llvm::ArrayRef &Libcalls, + std::vector &MustPreserveList, + llvm::SmallPtrSet &AsmUsed, + llvm::Mangler &Mangler); + bool determineTarget(std::string &errMsg); + + typedef llvm::StringMap StringSet; + + llvm::LLVMContext &Context; + llvm::Linker Linker; + llvm::TargetMachine *TargetMach; + bool EmitDwarfDebugInfo; + bool ScopeRestrictionsDone; + lto_codegen_model CodeModel; + StringSet MustPreserveSymbols; + StringSet AsmUndefinedRefs; + llvm::MemoryBuffer *NativeObjectFile; + std::vector CodegenOptions; + std::string MCpu; + std::string NativeObjectPath; + llvm::TargetOptions Options; +}; + +#endif // LTO_CODE_GENERATOR_H diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h new file mode 100644 index 0000000000000..f4693c8d2260a --- /dev/null +++ b/include/llvm/LTO/LTOModule.h @@ -0,0 +1,196 @@ +//===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===// +// +// 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 LTOModule class. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_MODULE_H +#define LTO_MODULE_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetMachine.h" +#include +#include + +// Forward references to llvm classes. +namespace llvm { + class Function; + class GlobalValue; + class MemoryBuffer; + class TargetOptions; + class Value; +} + +//===----------------------------------------------------------------------===// +/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// +struct LTOModule { +private: + typedef llvm::StringMap StringSet; + + struct NameAndAttributes { + const char *name; + uint32_t attributes; + bool isFunction; + const llvm::GlobalValue *symbol; + }; + + llvm::OwningPtr _module; + llvm::OwningPtr _target; + std::vector _symbols; + + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + llvm::StringMap _undefines; + std::vector _asm_undefines; + llvm::MCContext _context; + + // Use mangler to add GlobalPrefix to names to match linker names. + llvm::Mangler _mangler; + + LTOModule(llvm::Module *m, llvm::TargetMachine *t); +public: + /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM + /// bitcode. + static bool isBitcodeFile(const void *mem, size_t length); + static bool isBitcodeFile(const char *path); + + /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents + /// is LLVM bitcode for the specified triple. + static bool isBitcodeFileForTarget(const void *mem, + size_t length, + const char *triplePrefix); + static bool isBitcodeFileForTarget(const char *path, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership + /// of the buffer. The caller must have initialized the Targets, the + /// TargetMCs, the AsmPrinters, and the AsmParsers by calling: + /// + /// InitializeAllTargets(); + /// InitializeAllTargetMCs(); + /// InitializeAllAsmPrinters(); + /// InitializeAllAsmParsers(); + static LTOModule *makeLTOModule(const char* path, + llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t size, llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t map_size, + off_t offset, llvm::TargetOptions options, + std::string& errMsg); + static LTOModule *makeLTOModule(const void *mem, size_t length, + llvm::TargetOptions options, + std::string &errMsg); + + /// getTargetTriple - Return the Module's target triple. + const char *getTargetTriple() { + return _module->getTargetTriple().c_str(); + } + + /// setTargetTriple - Set the Module's target triple. + void setTargetTriple(const char *triple) { + _module->setTargetTriple(triple); + } + + /// getSymbolCount - Get the number of symbols + uint32_t getSymbolCount() { + return _symbols.size(); + } + + /// getSymbolAttributes - Get the attributes for a symbol at the specified + /// index. + lto_symbol_attributes getSymbolAttributes(uint32_t index) { + if (index < _symbols.size()) + return lto_symbol_attributes(_symbols[index].attributes); + return lto_symbol_attributes(0); + } + + /// getSymbolName - Get the name of the symbol at the specified index. + const char *getSymbolName(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].name; + return NULL; + } + + /// getLLVVMModule - Return the Module. + llvm::Module *getLLVVMModule() { return _module.get(); } + + /// getAsmUndefinedRefs - + const std::vector &getAsmUndefinedRefs() { + return _asm_undefines; + } + +private: + /// parseSymbols - Parse the symbols from the module and model-level ASM and + /// add them to either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); + + /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet + /// to a list to be resolved later. + void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); + + /// addDefinedSymbol - Add a defined symbol to the list. + void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); + + /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(const llvm::Function *f); + + /// addDefinedDataSymbol - Add a data symbol as defined to the list. + void addDefinedDataSymbol(const llvm::GlobalValue *v); + + /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the + /// defined or undefined lists. + bool addAsmGlobalSymbols(std::string &errMsg); + + /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the + /// defined list. + void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); + + /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to + /// the undefined list. + void addAsmGlobalSymbolUndef(const char *); + + /// addObjCClass - Parse i386/ppc ObjC class data structure. + void addObjCClass(const llvm::GlobalVariable *clgv); + + /// addObjCCategory - Parse i386/ppc ObjC category data structure. + void addObjCCategory(const llvm::GlobalVariable *clgv); + + /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(const llvm::GlobalVariable *clgv); + + /// objcClassNameFromExpression - Get string that the data pointer points + /// to. + bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); + + /// isTargetMatch - Returns 'true' if the memory buffer is for the specified + /// target triple. + static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule (private version). N.B. This + /// method takes ownership of the buffer. + static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, + llvm::TargetOptions options, + std::string &errMsg); + + /// makeBuffer - Create a MemoryBuffer from a memory range. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); +}; + +#endif // LTO_MODULE_H diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index ca1c13924e96c..8183fa2992a6a 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -56,12 +56,12 @@ namespace { (void) llvm::createLibCallAliasAnalysisPass(0); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); - (void) llvm::createBlockPlacementPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); + (void) llvm::createStructurizeCFGPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); (void) llvm::createCostModelAnalysisPass(); @@ -74,9 +74,6 @@ namespace { (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); - (void) llvm::createEdgeProfilerPass(); - (void) llvm::createOptimalEdgeProfilerPass(); - (void) llvm::createPathProfilerPass(); (void) llvm::createGCOVProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); @@ -94,6 +91,7 @@ namespace { (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopRerollPass(); (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); (void) llvm::createLoopIdiomPass(); @@ -102,18 +100,11 @@ namespace { (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); (void) llvm::createNoAAPass(); - (void) llvm::createNoProfileInfoPass(); (void) llvm::createObjCARCAliasAnalysisPass(); (void) llvm::createObjCARCAPElimPass(); (void) llvm::createObjCARCExpandPass(); (void) llvm::createObjCARCContractPass(); (void) llvm::createObjCARCOptPass(); - (void) llvm::createProfileEstimatorPass(); - (void) llvm::createProfileVerifierPass(); - (void) llvm::createPathProfileVerifierPass(); - (void) llvm::createProfileLoaderPass(); - (void) llvm::createProfileMetadataLoaderPass(); - (void) llvm::createPathProfileLoaderPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -129,7 +120,6 @@ namespace { (void) llvm::createRegionViewerPass(); (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); - (void) llvm::createSimplifyLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); (void) llvm::createStripNonDebugSymbolsPass(); @@ -163,6 +153,7 @@ namespace { (void) llvm::createLoopVectorizePass(); (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); + (void) llvm::createPartiallyInlineLibCallsPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h index 3667b8521d90c..4f37459eb403f 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker.h @@ -32,7 +32,9 @@ class Linker { Linker(Module *M); ~Linker(); + Module *getModule() const { return Composite; } + void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed if /// \p Mode is DestroySource and preserved if it is PreserveSource. diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 9a6b703408088..f946f41981c8a 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -10,7 +10,9 @@ #ifndef LLVM_MC_MCASMBACKEND_H #define LLVM_MC_MCASMBACKEND_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -32,6 +34,7 @@ class raw_ostream; class MCAsmBackend { MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + protected: // Can only create subclasses. MCAsmBackend(); @@ -42,7 +45,7 @@ public: virtual ~MCAsmBackend(); /// lifetime management - virtual void reset() { } + virtual void reset() {} /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. @@ -50,7 +53,7 @@ public: /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable /// non-standard ELFObjectWriters. - virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } @@ -71,9 +74,7 @@ public: /// hasDataInCodeSupport - Check whether this target implements data-in-code /// markers. If not, data region directives will be ignored. - bool hasDataInCodeSupport() const { - return HasDataInCodeSupport; - } + bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. @@ -128,8 +129,7 @@ public: /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; @@ -160,6 +160,12 @@ public: /// handleAssemblerFlag - Handle any target-specific assembler flags. /// By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} + + /// \brief Generate the compact unwind encoding for the CFI instructions. + virtual uint32_t + generateCompactUnwindEncoding(ArrayRef) const { + return 0; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index d020de3004f2e..7a99394621475 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -17,6 +17,7 @@ #define LLVM_MC_MCASMINFO_H #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MachineLocation.h" #include #include @@ -88,9 +89,13 @@ namespace llvm { /// 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 "$". + /// MinInstAlignment - Every possible instruction length is a multiple of + /// this value. Factored out in .debug_frame and .debug_line. + unsigned MinInstAlignment; // Defaults to 1. + + /// DollarIsPC - The '$' token, when not referencing an identifier or + /// constant, refers to the current PC. + bool DollarIsPC; // Defaults to false. /// SeparatorString - This string, if specified, is used to separate /// instructions from each other when on the same line. @@ -139,21 +144,9 @@ namespace llvm { /// 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; - - /// AllowUTF8 - This is true if the assembler accepts UTF-8 input. - // FIXME: Make this a more general encoding setting? - bool AllowUTF8; + /// \brief This is true if the assembler allows @ characters in symbol + /// names. Defaults to false. + bool AllowAtInName; /// UseDataRegionDirectives - This is true if data region markers should /// be printed as ".data_region/.end_data_region" directives. If false, @@ -195,13 +188,6 @@ namespace llvm { /// 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. @@ -242,11 +228,6 @@ namespace llvm { /// 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. @@ -273,14 +254,14 @@ namespace llvm { /// .file directive, this is true for ELF targets. bool HasSingleParameterDotFile; // Defaults to true. + /// hasIdentDirective - True if the target has a .ident directive, this is + /// true for ELF targets. + bool HasIdentDirective; // Defaults to false. + /// 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. @@ -318,10 +299,6 @@ namespace llvm { /// SupportsExceptionHandling - True if target supports exception handling. ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to - /// encode inline subroutine information. - bool DwarfUsesInlineInfoSection; // Defaults to false. - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally /// uses relocations for references to other .debug_* sections. bool DwarfUsesRelocationsAcrossSections; @@ -332,15 +309,15 @@ namespace llvm { //===--- Prologue State ----------------------------------------------===// - std::vector InitialFrameState; + std::vector InitialFrameState; 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); + static unsigned getSLEB128Size(int64_t Value); + static unsigned getULEB128Size(uint64_t Value); /// getPointerSize - Get the pointer size in bytes. unsigned getPointerSize() const { @@ -367,17 +344,17 @@ namespace llvm { // Data directive accessors. // - const char *getData8bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + const char *getData8bitsDirective() const { + return Data8bitsDirective; } - const char *getData16bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + const char *getData16bitsDirective() const { + return Data16bitsDirective; } - const char *getData32bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + const char *getData32bitsDirective() const { + return Data32bitsDirective; } - const char *getData64bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + const char *getData64bitsDirective() const { + return Data64bitsDirective; } const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } @@ -428,8 +405,11 @@ namespace llvm { unsigned getMaxInstLength() const { return MaxInstLength; } - const char *getPCSymbol() const { - return PCSymbol; + unsigned getMinInstAlignment() const { + return MinInstAlignment; + } + bool getDollarIsPC() const { + return DollarIsPC; } const char *getSeparatorString() const { return SeparatorString; @@ -475,17 +455,8 @@ namespace llvm { unsigned getAssemblerDialect() const { return AssemblerDialect; } - bool doesAllowQuotesInName() const { - return AllowQuotesInName; - } - bool doesAllowNameToStartWithDigit() const { - return AllowNameToStartWithDigit; - } - bool doesAllowPeriodsInName() const { - return AllowPeriodsInName; - } - bool doesAllowUTF8() const { - return AllowUTF8; + bool doesAllowAtInName() const { + return AllowAtInName; } bool doesSupportDataRegionDirectives() const { return UseDataRegionDirectives; @@ -511,9 +482,6 @@ namespace llvm { const char *getGlobalDirective() const { return GlobalDirective; } - const char *getExternDirective() const { - return ExternDirective; - } bool hasSetDirective() const { return HasSetDirective; } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; @@ -526,8 +494,8 @@ namespace llvm { } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } 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; } @@ -557,9 +525,6 @@ namespace llvm { ExceptionsType == ExceptionHandling::ARM || ExceptionsType == ExceptionHandling::Win64); } - bool doesDwarfUseInlineInfoSection() const { - return DwarfUsesInlineInfoSection; - } bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } @@ -567,11 +532,11 @@ namespace llvm { return DwarfRegNumForCFI; } - void addInitialFrameState(MCSymbol *label, const MachineLocation &D, - const MachineLocation &S) { - InitialFrameState.push_back(MachineMove(label, D, S)); + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); } - const std::vector &getInitialFrameState() const { + + const std::vector &getInitialFrameState() const { return InitialFrameState; } }; diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h new file mode 100644 index 0000000000000..27fea84e7a6da --- /dev/null +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -0,0 +1,23 @@ +//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- 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_MCASMINFOELF_H +#define LLVM_MC_MCASMINFOELF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { +class MCAsmInfoELF : public MCAsmInfo { + virtual void anchor(); +protected: + MCAsmInfoELF(); +}; +} + +#endif diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 38a70f0adf016..8735a55ce044e 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -19,6 +19,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include #include // FIXME: Shouldn't be needed. namespace llvm { @@ -816,6 +817,9 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector FileNameVectorType; + typedef FileNameVectorType::const_iterator const_file_name_iterator; + typedef std::vector::const_iterator const_indirect_symbol_iterator; typedef std::vector::iterator indirect_symbol_iterator; @@ -859,6 +863,9 @@ private: /// The list of linker options to propagate into the object file. std::vector > LinkerOptions; + /// List of declared file names + FileNameVectorType FileNames; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -1152,6 +1159,20 @@ public: return *Entry; } + const_file_name_iterator file_names_begin() const { + return FileNames.begin(); + } + + const_file_name_iterator file_names_end() const { + return FileNames.end(); + } + + void addFileName(StringRef FileName) { + if (std::find(file_names_begin(), file_names_end(), FileName) == + file_names_end()) + FileNames.push_back(FileName); + } + /// @} void dump(); diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h index ae5bf0bc20693..eab32d691fa84 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAtom.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAtom.h - MCAtom class ---------------------*- C++ -*-===// +//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,13 +9,14 @@ // // This file contains the declaration of the MCAtom class, which is used to // represent a contiguous region in a decoded object that is uniformly data or -// instructions; +// instructions. // //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MCATOM_H #define LLVM_MC_MCATOM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include @@ -24,45 +25,175 @@ namespace llvm { class MCModule; -/// MCData - An entry in a data MCAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; +class MCAtom; +class MCTextAtom; +class MCDataAtom; -/// MCAtom - Represents a contiguous range of either instructions (a TextAtom) +/// \brief Represents a contiguous range of either instructions (a TextAtom) /// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. class MCAtom { - friend class MCModule; - typedef enum { TextAtom, DataAtom } AtomType; - - AtomType Type; + virtual void anchor(); +public: + virtual ~MCAtom() {} + + enum AtomKind { TextAtom, DataAtom }; + AtomKind getKind() const { return Kind; } + + /// \brief Get the start address of the atom. + uint64_t getBeginAddr() const { return Begin; } + /// \brief Get the end address, i.e. the last one inside the atom. + uint64_t getEndAddr() const { return End; } + + /// \name Atom modification methods: + /// When modifying a TextAtom, keep instruction boundaries in mind. + /// For instance, split must me given the start address of an instruction. + /// @{ + + /// \brief Splits the atom in two at a given address. + /// \param SplitPt Address at which to start a new atom, splitting this one. + /// \returns The newly created atom starting at \p SplitPt. + virtual MCAtom *split(uint64_t SplitPt) = 0; + + /// \brief Truncates an atom, discarding everything after \p TruncPt. + /// \param TruncPt Last byte address to be contained in this atom. + virtual void truncate(uint64_t TruncPt) = 0; + /// @} + + /// \name Naming: + /// + /// This is mostly for display purposes, and may contain anything that hints + /// at what the atom contains: section or symbol name, BB start address, .. + /// @{ + StringRef getName() const { return Name; } + void setName(StringRef NewName) { Name = NewName.str(); } + /// @} + +protected: + const AtomKind Kind; + std::string Name; MCModule *Parent; uint64_t Begin, End; - std::vector > Text; - std::vector Data; + friend class MCModule; + MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) + : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } + + /// \name Atom remapping helpers + /// @{ + + /// \brief Remap the atom, using the given range, updating Begin/End. + /// One or both of the bounds can remain the same, but overlapping with other + /// atoms in the module is still forbidden. + void remap(uint64_t NewBegin, uint64_t NewEnd); + + /// \brief Remap the atom to prepare for a truncation at TruncPt. + /// Equivalent to: + /// \code + /// // Bound checks + /// remap(Begin, TruncPt); + /// \endcode + void remapForTruncate(uint64_t TruncPt); + + /// \brief Remap the atom to prepare for a split at SplitPt. + /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. + /// The current atom is truncated to \p LEnd. + void remapForSplit(uint64_t SplitPt, + uint64_t &LBegin, uint64_t &LEnd, + uint64_t &RBegin, uint64_t &REnd); + /// @} +}; - // Private constructor - only callable by MCModule - MCAtom(AtomType T, MCModule *P, uint64_t B, uint64_t E) - : Type(T), Parent(P), Begin(B), End(E) { } +/// \name Text atom +/// @{ +/// \brief An entry in an MCTextAtom: a disassembled instruction. +/// NOTE: Both the Address and Size field are actually redundant when taken in +/// the context of the text atom, and may better be exposed in an iterator +/// instead of stored in the atom, which would replace this class. +class MCDecodedInst { public: - bool isTextAtom() const { return Type == TextAtom; } - bool isDataAtom() const { return Type == DataAtom; } + MCInst Inst; + uint64_t Address; + uint64_t Size; + MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) + : Inst(Inst), Address(Address), Size(Size) {} +}; + +/// \brief An atom consisting of disassembled instructions. +class MCTextAtom : public MCAtom { +private: + typedef std::vector InstListTy; + InstListTy Insts; - void addInst(const MCInst &I, uint64_t Address, unsigned Size); + /// \brief The address of the next appended instruction, i.e., the + /// address immediately after the last instruction in the atom. + uint64_t NextInstAddress; +public: + /// Append an instruction, expanding the atom if necessary. + void addInst(const MCInst &Inst, uint64_t Size); + + /// \name Instruction list access + /// @{ + typedef InstListTy::const_iterator const_iterator; + const_iterator begin() const { return Insts.begin(); } + const_iterator end() const { return Insts.end(); } + + const MCDecodedInst &back() const { return Insts.back(); } + const MCDecodedInst &at(size_t n) const { return Insts.at(n); } + size_t size() const { return Insts.size(); } + /// @} + + /// \name Atom type specific split/truncate logic. + /// @{ + MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} + + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} +}; +/// @} + +/// \name Data atom +/// @{ + +/// \brief An entry in an MCDataAtom. +// NOTE: This may change to a more complex type in the future. +typedef uint8_t MCData; + +/// \brief An atom consising of a sequence of bytes. +class MCDataAtom : public MCAtom { + std::vector Data; + +public: + /// Append a data entry, expanding the atom if necessary. void addData(const MCData &D); - /// split - Splits the atom in two at a given address, which must align with - /// and instruction boundary if this is a TextAtom. Returns the newly created - /// atom representing the high part of the split. - MCAtom *split(uint64_t SplitPt); + /// Get a reference to the data in this atom. + ArrayRef getData() const { return Data; } + + /// \name Atom type specific split/truncate logic. + /// @{ + MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} - /// truncate - Truncates an atom so that TruncPt is the last byte address - /// contained in the atom. - void truncate(uint64_t TruncPt); + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(DataAtom, P, Begin, End) { + Data.reserve(End + 1 - Begin); + } }; } #endif - diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index d1765e1240a47..84ce934d822ee 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -42,6 +42,9 @@ namespace llvm { CodeModel::Model getCodeModel() const { return CMModel; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } }; } // namespace llvm diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 0db3dee2ff050..c8b66261bfea7 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" @@ -37,6 +38,7 @@ namespace llvm { class Twine; class MCSectionMachO; class MCSectionELF; + class MCSectionCOFF; /// MCContext - Context object for machine code objects. This class owns all /// of the sections that it creates. @@ -51,10 +53,10 @@ namespace llvm { const SourceMgr *SrcMgr; /// The MCAsmInfo for this target. - const MCAsmInfo &MAI; + const MCAsmInfo *MAI; /// The MCRegisterInfo for this target. - const MCRegisterInfo &MRI; + const MCRegisterInfo *MRI; /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; @@ -97,7 +99,7 @@ namespace llvm { bool SecureLogUsed; /// The compilation directory to use for DW_AT_comp_dir. - std::string CompilationDir; + SmallString<128> CompilationDir; /// The main file name if passed in explicitly. std::string MainFileName; @@ -163,16 +165,16 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } - const MCAsmInfo &getAsmInfo() const { return MAI; } + const MCAsmInfo *getAsmInfo() const { return MAI; } - const MCRegisterInfo &getRegisterInfo() const { return MRI; } + const MCRegisterInfo *getRegisterInfo() const { return MRI; } const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } @@ -254,14 +256,18 @@ namespace llvm { const MCSectionELF *CreateELFGroupSection(); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - int Selection, SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + int Selection, + const MCSectionCOFF *Assoc = 0); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind) { - return getCOFFSection (Section, Characteristics, 0, Kind); - } + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section); /// @} @@ -272,7 +278,7 @@ namespace llvm { /// This can be overridden by clients which want to control the reported /// compilation directory and have it be something other than the current /// working directory. - const std::string &getCompilationDir() const { return CompilationDir; } + StringRef getCompilationDir() const { return CompilationDir; } /// \brief Set the compilation directory for DW_AT_comp_dir /// Override the default (CWD) compilation directory. @@ -406,7 +412,7 @@ namespace llvm { void Deallocate(void *Ptr) { } - // Unrecoverable error has occured. Display the best diagnostic we can + // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg); diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 36fbcb02d9f6f..83f26ef3edb9e 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -10,6 +10,9 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/MC/MCRelocationInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -55,7 +58,8 @@ public: /// Constructor - Performs initial setup for the disassembler. MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), DisInfo(0), Ctx(0), - STI(STI), CommentStream(0) {} + STI(STI), Symbolizer(0), + CommentStream(0) {} virtual ~MCDisassembler(); @@ -81,7 +85,6 @@ public: uint64_t address, raw_ostream &vStream, raw_ostream &cStream) const = 0; - private: // // Hooks for symbolic disassembly via the public 'C' interface. @@ -95,20 +98,32 @@ private: // The assembly context for creating symbols and MCExprs in place of // immediate operands when there is symbolic information. MCContext *Ctx; + protected: // Subtarget information, for instruction decoding predicates if required. const MCSubtargetInfo &STI; + OwningPtr Symbolizer; public: - void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, - LLVMSymbolLookupCallback symbolLookUp, - void *disInfo, - MCContext *ctx) { - GetOpInfo = getOpInfo; - SymbolLookUp = symbolLookUp; - DisInfo = disInfo; - Ctx = ctx; - } + // Helpers around MCSymbolizer + bool tryAddingSymbolicOperand(MCInst &Inst, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) const; + + void tryAddingPcLoadReferenceComment(int64_t Value, uint64_t Address) const; + + /// Set \p Symzer as the current symbolizer. + /// This takes ownership of \p Symzer, and deletes the previously set one. + void setSymbolizer(OwningPtr &Symzer); + + /// Sets up an external symbolizer that uses the C API callbacks. + void setupForSymbolicDisassembly(LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + OwningPtr &RelInfo); + LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { return SymbolLookUp; @@ -116,6 +131,8 @@ public: void *getDisInfoBlock() const { return DisInfo; } MCContext *getMCContext() const { return Ctx; } + const MCSubtargetInfo& getSubtargetInfo() const { return STI; } + // Marked mutable because we cache it inside the disassembler, rather than // having to pass it around as an argument through all the autogenerated code. mutable raw_ostream *CommentStream; diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1a392e8755ee3..65b920bf232e7 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -23,403 +23,445 @@ #include namespace llvm { - class MCContext; - class MCObjectWriter; - class MCSection; - class MCStreamer; - class MCSymbol; - class SourceMgr; - class SMLoc; - - /// 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) +class MCAsmBackend; +class MCContext; +class MCSection; +class MCStreamer; +class MCSymbol; +class SourceMgr; +class SMLoc; + +/// 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&) LLVM_DELETED_FUNCTION; - void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - 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 \p 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; + MCDwarfFile(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + void operator=(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + +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 \p 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_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_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) +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. + // 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; } +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; } + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. - unsigned getColumn() const { return Column; } + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. - unsigned getFlags() const { return Flags; } + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. - unsigned getIsa() const { return Isa; } + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. - unsigned getDiscriminator() const { return Discriminator; } + /// 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; } + /// 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; } + /// 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; } + /// 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; } + /// 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; } + /// 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; - } - }; + /// 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 &) LLVM_DELETED_FUNCTION; + void operator=(const MCLineSection &) LLVM_DELETED_FUNCTION; + +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, unsigned CUID) { + MCLineDivisions[CUID].push_back(LineEntry); + } - /// 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); - }; + typedef std::vector MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + typedef std::map MCLineDivisionMap; + +private: + // A collection of MCLineEntry for each Compile Unit ID. + MCLineDivisionMap MCLineDivisions; - /// 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&) LLVM_DELETED_FUNCTION; - void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; - - 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, unsigned CUID) { - MCLineDivisions[CUID].push_back(LineEntry); - } - - typedef std::vector MCLineEntryCollection; - typedef MCLineEntryCollection::iterator iterator; - typedef MCLineEntryCollection::const_iterator const_iterator; - typedef std::map MCLineDivisionMap; - - private: - // A collection of MCLineEntry for each Compile Unit ID. - MCLineDivisionMap MCLineDivisions; - - public: - // Returns whether MCLineSection contains entries for a given Compile - // Unit ID. - bool containEntriesForID(unsigned CUID) const { - return MCLineDivisions.count(CUID); - } - // Returns the collection of MCLineEntry for a given Compile Unit ID. - const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { - MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); - assert(CIter != MCLineDivisions.end()); - return CIter->second; - } +public: + // Returns whether MCLineSection contains entries for a given Compile + // Unit ID. + bool containEntriesForID(unsigned CUID) const { + return MCLineDivisions.count(CUID); + } + // Returns the collection of MCLineEntry for a given Compile Unit ID. + const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { + MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); + assert(CIter != MCLineDivisions.end()); + return CIter->second; + } +}; + +class MCDwarfFileTable { +public: + // + // This emits the Dwarf file and the line tables for all Compile Units. + // + static const MCSymbol *Emit(MCStreamer *MCOS); + // + // This emits the Dwarf file and the line tables for a given Compile Unit. + // + static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +}; + +class MCDwarfLineAddr { +public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(MCContext &Context, 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); +}; + +class MCGenDwarfInfo { +public: + // + // When generating dwarf for assembly source files this emits the Dwarf + // sections. + // + static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); +}; + +// When generating dwarf for assembly source files this is the info that is +// needed to be gathered for each symbol that will have a dwarf label. +class MCGenDwarfLabelEntry { +private: + // Name of the symbol without a leading underbar, if any. + StringRef Name; + // The dwarf file number this symbol is in. + unsigned FileNumber; + // The line number this symbol is at. + unsigned LineNumber; + // The low_pc for the dwarf label is taken from this symbol. + MCSymbol *Label; + +public: + MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, + MCSymbol *label) + : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), + Label(label) {} + + StringRef getName() const { return Name; } + unsigned getFileNumber() const { return FileNumber; } + unsigned getLineNumber() const { return LineNumber; } + MCSymbol *getLabel() const { return Label; } + + // This is called when label is created when we are generating dwarf for + // assembly source files. + static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, + SMLoc &Loc); +}; + +class MCCFIInstruction { +public: + enum OpType { + OpSameValue, + OpRememberState, + OpRestoreState, + OpOffset, + OpDefCfaRegister, + OpDefCfaOffset, + OpDefCfa, + OpRelOffset, + OpAdjustCfaOffset, + OpEscape, + OpRestore, + OpUndefined, + OpRegister, + OpWindowSave }; - class MCDwarfFileTable { - public: - // - // This emits the Dwarf file and the line tables for all Compile Units. - // - static const MCSymbol *Emit(MCStreamer *MCOS); - // - // This emits the Dwarf file and the line tables for a given Compile Unit. - // - static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +private: + OpType Operation; + MCSymbol *Label; + unsigned Register; + union { + int Offset; + unsigned Register2; }; + std::vector Values; - 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); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) + : Operation(Op), Label(L), Register(R), Offset(O), + Values(V.begin(), V.end()) { + assert(Op != OpRegister); + } - /// Utility function to emit the encoding to a streamer. - static void Emit(MCStreamer *MCOS, - int64_t LineDelta,uint64_t AddrDelta); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) + : Operation(Op), Label(L), Register(R1), Register2(R2) { + assert(Op == OpRegister); + } - /// Utility function to write the encoding to an object writer. - static void Write(MCObjectWriter *OW, - int64_t LineDelta, uint64_t AddrDelta); - }; +public: + /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from + /// Register and add Offset to it. + static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); + } - class MCGenDwarfInfo { - public: - // - // When generating dwarf for assembly source files this emits the Dwarf - // sections. - // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); - }; + /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// on Register will be used instead of the old one. Offset remains the same. + static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); + } - // When generating dwarf for assembly source files this is the info that is - // needed to be gathered for each symbol that will have a dwarf label. - class MCGenDwarfLabelEntry { - private: - // Name of the symbol without a leading underbar, if any. - StringRef Name; - // The dwarf file number this symbol is in. - unsigned FileNumber; - // The line number this symbol is at. - unsigned LineNumber; - // The low_pc for the dwarf label is taken from this symbol. - MCSymbol *Label; - - public: - MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, - unsigned lineNumber, MCSymbol *label) : - Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} - - StringRef getName() const { return Name; } - unsigned getFileNumber() const { return FileNumber; } - unsigned getLineNumber() const { return LineNumber; } - MCSymbol *getLabel() const { return Label; } - - // This is called when label is created when we are generating dwarf for - // assembly source files. - static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, - SMLoc &Loc); - }; + /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// remains the same, but offset is new. Note that it is the absolute offset + /// that will be added to a defined register to the compute CFA address. + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); + } - class MCCFIInstruction { - public: - enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, - OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, - OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, - OpRegister }; - private: - OpType Operation; - MCSymbol *Label; - unsigned Register; - union { - int Offset; - unsigned Register2; - }; - std::vector Values; - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : - Operation(Op), Label(L), Register(R), Offset(O), - Values(V.begin(), V.end()) { - assert(Op != OpRegister); - } - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : - Operation(Op), Label(L), Register(R1), Register2(R2) { - assert(Op == OpRegister); - } - - public: - static MCCFIInstruction - createOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createDefCfaRegister(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); - } - - static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { - return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); - } - - static MCCFIInstruction - createDefCfa(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); - } - - static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpUndefined, L, Register, 0, ""); - } - - static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpRestore, L, Register, 0, ""); - } - - static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpSameValue, L, Register, 0, ""); - } - - static MCCFIInstruction createRestoreState(MCSymbol *L) { - return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); - } - - static MCCFIInstruction createRememberState(MCSymbol *L) { - return MCCFIInstruction(OpRememberState, L, 0, 0, ""); - } - - static MCCFIInstruction - createRelOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createAdjustCfaOffset(MCSymbol *L, int Adjustment) { - return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); - } - - static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { - return MCCFIInstruction(OpEscape, L, 0, 0, Vals); - } - - static MCCFIInstruction - createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { - return MCCFIInstruction(OpRegister, L, Register1, Register2); - } - - OpType getOperation() const { return Operation; } - MCSymbol *getLabel() const { return Label; } - - unsigned getRegister() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRestore || Operation == OpUndefined || - Operation == OpSameValue || Operation == OpDefCfaRegister || - Operation == OpRelOffset || Operation == OpRegister); - return Register; - } - - unsigned getRegister2() const { - assert(Operation == OpRegister); - return Register2; - } - - int getOffset() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRelOffset || Operation == OpDefCfaOffset || - Operation == OpAdjustCfaOffset); - return Offset; - } - - const StringRef getValues() const { - assert(Operation == OpEscape); - return StringRef(&Values[0], Values.size()); - } - }; + /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// Offset is a relative value that is added/subtracted from the previous + /// offset. + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { + return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); + } - struct MCDwarfFrameInfo { - MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), - Function(0), Instructions(), PersonalityEncoding(), - LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *Personality; - const MCSymbol *Lsda; - const MCSymbol *Function; - std::vector Instructions; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - uint32_t CompactUnwindEncoding; - bool IsSignalFrame; - }; + /// \brief .cfi_offset Previous value of Register is saved at offset Offset + /// from CFA. + static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); + } - class MCDwarfFrameEmitter { - public: - // - // This emits the frame info section. - // - static void Emit(MCStreamer &streamer, bool usingCFI, - bool isEH); - static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); - }; + /// \brief .cfi_rel_offset Previous value of Register is saved at offset + /// Offset from the current CFA register. This is transformed to .cfi_offset + /// using the known displacement of the CFA register from the CFA. + static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); + } + + /// \brief .cfi_register Previous value of Register1 is saved in + /// register Register2. + static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, + unsigned Register2) { + return MCCFIInstruction(OpRegister, L, Register1, Register2); + } + + /// \brief .cfi_window_save SPARC register window is saved. + static MCCFIInstruction createWindowSave(MCSymbol *L) { + return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); + } + + /// \brief .cfi_restore says that the rule for Register is now the same as it + /// was at the beginning of the function, after all initial instructions added + /// by .cfi_startproc were executed. + static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpRestore, L, Register, 0, ""); + } + + /// \brief .cfi_undefined From now on the previous value of Register can't be + /// restored anymore. + static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpUndefined, L, Register, 0, ""); + } + + /// \brief .cfi_same_value Current value of Register is the same as in the + /// previous frame. I.e., no restoration is needed. + static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpSameValue, L, Register, 0, ""); + } + + /// \brief .cfi_remember_state Save all current rules for all registers. + static MCCFIInstruction createRememberState(MCSymbol *L) { + return MCCFIInstruction(OpRememberState, L, 0, 0, ""); + } + + /// \brief .cfi_restore_state Restore the previously saved state. + static MCCFIInstruction createRestoreState(MCSymbol *L) { + return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); + } + + /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// info. + static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { + return MCCFIInstruction(OpEscape, L, 0, 0, Vals); + } + + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + + unsigned getRegister() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRestore || Operation == OpUndefined || + Operation == OpSameValue || Operation == OpDefCfaRegister || + Operation == OpRelOffset || Operation == OpRegister); + return Register; + } + + unsigned getRegister2() const { + assert(Operation == OpRegister); + return Register2; + } + + int getOffset() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRelOffset || Operation == OpDefCfaOffset || + Operation == OpAdjustCfaOffset); + return Offset; + } + + const StringRef getValues() const { + assert(Operation == OpEscape); + return StringRef(&Values[0], Values.size()); + } +}; + +struct MCDwarfFrameInfo { + MCDwarfFrameInfo() + : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), + PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), + IsSignalFrame(false) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + const MCSymbol *Function; + std::vector Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + uint32_t CompactUnwindEncoding; + bool IsSignalFrame; +}; + +class MCDwarfFrameEmitter { +public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer, MCAsmBackend *MAB, + bool usingCFI, bool isEH); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); +}; } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 65dd1e8998cc6..92ad1b1a46fec 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -42,18 +42,6 @@ struct ELFRelocationEntry { const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), r_addend(Addend), Fixup(&Fixup) {} - - // Support lexicographic sorting. - bool operator<(const ELFRelocationEntry &RE) const { - if (RE.r_offset != r_offset) - return RE.r_offset < r_offset; - if (Type != RE.Type) - return Type < RE.Type; - if (Index != RE.Index) - return Index < RE.Index; - llvm_unreachable("ELFRelocs might be unstable!"); - return 0; - } }; class MCELFObjectTargetWriter { @@ -94,8 +82,6 @@ public: virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const; - virtual void adjustFixupOffset(const MCFixup &Fixup, - uint64_t &RelocOffset); virtual void sortRelocs(const MCAssembler &Asm, std::vector &Relocs); diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 55c05b0363ddb..4e24dcfacd507 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -28,20 +28,17 @@ class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { -protected: - MCELFStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Kind, Context, TAB, OS, Emitter) {} - public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter), + SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter, - Assembler) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter, Assembler), + SeenIdent(false) {} virtual ~MCELFStreamer(); @@ -57,7 +54,7 @@ public: virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -77,21 +74,17 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitFileDirective(StringRef Filename); - virtual void EmitTCEntry(const MCSymbol &S); + virtual void EmitIdent(StringRef IdentString); virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); - virtual void FinishImpl(); - /// @} + virtual void Flush(); - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_ELFStreamer || S->getKind() == SK_ARMELFStreamer; - } + virtual void FinishImpl(); private: virtual void EmitInstToFragment(const MCInst &Inst); @@ -103,6 +96,8 @@ private: void fixSymbolsInTLSFixups(const MCExpr *expr); + bool SeenIdent; + struct LocalCommon { MCSymbolData *SD; uint64_t Size; @@ -121,6 +116,11 @@ private: void SetSectionBss(); }; +MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + bool RelaxAll, bool NoExecStack, + bool IsThumb); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index 2225ea07868f1..d0e1dace99d1a 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -27,7 +27,7 @@ namespace llvm { ELF_Other_Shift = 10 // Shift value for other flags. }; - enum SymbolFlags { + enum ELFSymbolFlags { 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), diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index a2c5bd3f76613..5d559744da972 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -171,26 +171,56 @@ public: VK_ARM_TARGET2, VK_ARM_PREL31, - VK_PPC_TOC, // TOC base - VK_PPC_TOC_ENTRY, // TOC entry - VK_PPC_DARWIN_HA16, // ha16(symbol) - VK_PPC_DARWIN_LO16, // lo16(symbol) - VK_PPC_GAS_HA16, // symbol@ha - VK_PPC_GAS_LO16, // symbol@l - VK_PPC_TPREL16_HA, // symbol@tprel@ha - VK_PPC_TPREL16_LO, // symbol@tprel@l - VK_PPC_DTPREL16_HA, // symbol@dtprel@ha - VK_PPC_DTPREL16_LO, // symbol@dtprel@l - VK_PPC_TOC16_HA, // symbol@toc@ha - VK_PPC_TOC16_LO, // symbol@toc@l - VK_PPC_GOT_TPREL16_HA, // symbol@got@tprel@ha - VK_PPC_GOT_TPREL16_LO, // symbol@got@tprel@l + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + VK_PPC_TOC_LO, // symbol@toc@l + VK_PPC_TOC_HI, // symbol@toc@h + VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_DTPMOD, // symbol@dtpmod + VK_PPC_TPREL, // symbol@tprel + VK_PPC_TPREL_LO, // symbol@tprel@l + VK_PPC_TPREL_HI, // symbol@tprel@h + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL, // symbol@dtprel + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha VK_PPC_TLS, // symbol@tls - VK_PPC_GOT_TLSGD16_HA, // symbol@got@tlsgd@ha - VK_PPC_GOT_TLSGD16_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha VK_PPC_TLSGD, // symbol@tlsgd - VK_PPC_GOT_TLSLD16_HA, // symbol@got@tlsld@ha - VK_PPC_GOT_TLSLD16_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld VK_Mips_GPREL, diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCExternalSymbolizer.h new file mode 100644 index 0000000000000..c942adca3b4d0 --- /dev/null +++ b/include/llvm/MC/MCExternalSymbolizer.h @@ -0,0 +1,58 @@ +//===-- llvm/MC/MCExternalSymbolizer.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 MCExternalSymbolizer class, which +// enables library users to provide callbacks (through the C API) to do the +// symbolization externally. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXTERNALSYMBOLIZER_H +#define LLVM_MC_MCEXTERNALSYMBOLIZER_H + +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCSymbolizer.h" + +namespace llvm { + +/// \brief Symbolize using user-provided, C API, callbacks. +/// +/// See llvm-c/Disassembler.h. +class MCExternalSymbolizer : public MCSymbolizer { + + /// \name Hooks for symbolic disassembly via the public 'C' interface. + /// @{ + /// The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + /// The function to lookup a symbol name. + LLVMSymbolLookupCallback SymbolLookUp; + /// The pointer to the block of symbolic information for above call back. + void *DisInfo; + /// @} + +public: + MCExternalSymbolizer(MCContext &Ctx, + OwningPtr &RelInfo, + LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, + void *disInfo) + : MCSymbolizer(Ctx, RelInfo), + GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} + + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize); + void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream, + int64_t Value, uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/MC/MCFunction.h b/include/llvm/MC/MCFunction.h new file mode 100644 index 0000000000000..22c9192ac4b5a --- /dev/null +++ b/include/llvm/MC/MCFunction.h @@ -0,0 +1,142 @@ +//===-- llvm/MC/MCFunction.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 data structures to hold a CFG reconstructed from +// machine code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFUNCTION_H +#define LLVM_MC_MCFUNCTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCInst.h" +#include +#include + +namespace llvm { + +class MCFunction; +class MCModule; +class MCTextAtom; + +/// \brief Basic block containing a sequence of disassembled instructions. +/// The basic block is backed by an MCTextAtom, which holds the instructions, +/// and the address range it covers. +/// Create a basic block using MCFunction::createBlock. +class MCBasicBlock { + const MCTextAtom *Insts; + + // MCFunction owns the basic block. + MCFunction *Parent; + friend class MCFunction; + MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); + + /// \name Predecessors/Successors, to represent the CFG. + /// @{ + typedef std::vector BasicBlockListTy; + BasicBlockListTy Successors; + BasicBlockListTy Predecessors; + /// @} +public: + + /// \brief Get the backing MCTextAtom, containing the instruction sequence. + const MCTextAtom *getInsts() const { return Insts; } + + /// \name Get the owning MCFunction. + /// @{ + const MCFunction *getParent() const { return Parent; } + MCFunction *getParent() { return Parent; } + /// @} + + /// MC CFG access: Predecessors/Successors. + /// @{ + typedef BasicBlockListTy::const_iterator succ_const_iterator; + succ_const_iterator succ_begin() const { return Successors.begin(); } + succ_const_iterator succ_end() const { return Successors.end(); } + + typedef BasicBlockListTy::const_iterator pred_const_iterator; + pred_const_iterator pred_begin() const { return Predecessors.begin(); } + pred_const_iterator pred_end() const { return Predecessors.end(); } + + void addSuccessor(const MCBasicBlock *MCBB); + bool isSuccessor(const MCBasicBlock *MCBB) const; + + void addPredecessor(const MCBasicBlock *MCBB); + bool isPredecessor(const MCBasicBlock *MCBB) const; + + /// \brief Split block, mirrorring NewAtom = Insts->split(..). + /// This moves all successors to \p SplitBB, and + /// adds a fallthrough to it. + /// \p SplitBB The result of splitting Insts, a basic block directly following + /// this basic block. + void splitBasicBlock(MCBasicBlock *SplitBB); + /// @} +}; + +/// \brief Represents a function in machine code, containing MCBasicBlocks. +/// MCFunctions are created by MCModule. +class MCFunction { + MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; + MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; + + std::string Name; + MCModule *ParentModule; + typedef std::vector BasicBlockListTy; + BasicBlockListTy Blocks; + + // MCModule owns the function. + friend class MCModule; + MCFunction(StringRef Name, MCModule *Parent); + ~MCFunction(); + +public: + /// \brief Create an MCBasicBlock backed by Insts and add it to this function. + /// \param Insts Sequence of straight-line code backing the basic block. + /// \returns The newly created basic block. + MCBasicBlock &createBlock(const MCTextAtom &Insts); + + StringRef getName() const { return Name; } + + /// \name Get the owning MC Module. + /// @{ + const MCModule *getParent() const { return ParentModule; } + MCModule *getParent() { return ParentModule; } + /// @} + + /// \name Access to the function's basic blocks. No ordering is enforced, + /// except that the first block is the entry block. + /// @{ + /// \brief Get the entry point basic block. + const MCBasicBlock *getEntryBlock() const { return front(); } + MCBasicBlock *getEntryBlock() { return front(); } + + bool empty() const { return Blocks.empty(); } + + typedef BasicBlockListTy::const_iterator const_iterator; + typedef BasicBlockListTy:: iterator iterator; + const_iterator begin() const { return Blocks.begin(); } + iterator begin() { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + iterator end() { return Blocks.end(); } + + const MCBasicBlock* front() const { return Blocks.front(); } + MCBasicBlock* front() { return Blocks.front(); } + const MCBasicBlock* back() const { return Blocks.back(); } + MCBasicBlock* back() { return Blocks.back(); } + + /// \brief Find the basic block, if any, that starts at \p StartAddr. + const MCBasicBlock *find(uint64_t StartAddr) const; + MCBasicBlock *find(uint64_t StartAddr); + /// @} +}; + +} + +#endif diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index a18cbd94bbbf1..b4258bef04ce1 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -21,6 +21,13 @@ class MCInstrInfo; class MCRegisterInfo; class StringRef; +namespace HexStyle { + enum Style { + C, ///< 0xff + Asm ///< 0ffh + }; +} + /// MCInstPrinter - This is an instance of a target assembly language printer /// that converts an MCInst to valid target assembly syntax. class MCInstPrinter { @@ -34,7 +41,7 @@ protected: const MCRegisterInfo &MRI; /// The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// True if we are printing marked up assembly. bool UseMarkup; @@ -42,13 +49,16 @@ protected: /// True if we are printing immediates as hex. bool PrintImmHex; + /// Which style to use for printing hexadecimal values. + HexStyle::Style PrintHexStyle; + /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), - UseMarkup(0), PrintImmHex(0) {} + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); @@ -67,8 +77,8 @@ public: /// printRegName - Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } @@ -80,8 +90,16 @@ public: bool getPrintImmHex() const { return PrintImmHex; } void setPrintImmHex(bool Value) { PrintImmHex = Value; } + HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; } + void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } + /// Utility function to print immediates in decimal or hex. - format_object1 formatImm(const int64_t Value) const; + format_object1 formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + + /// Utility functions to print decimal/hexadecimal values. + format_object1 formatDec(const int64_t Value) const; + format_object1 formatHex(const int64_t Value) const; + format_object1 formatHex(const uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index acad6336aca73..17bfd1582ae59 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -52,10 +52,15 @@ public: return Info->get(Inst.getOpcode()).isReturn(); } + virtual bool isTerminator(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isTerminator(); + } + /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Otherwise return -1. - virtual uint64_t - evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const; + /// branch targets. Return true on success, and the address in Target. + virtual bool + evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const; }; } diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 9b5415add2413..214b593f4ad6e 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -17,6 +17,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -145,6 +146,10 @@ public: const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + // A complex method to determine is a certain is deprecated or not, and return + // the reason for deprecation. + bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -158,6 +163,20 @@ public: return -1; } + /// \brief Returns true if a certain instruction is deprecated and if so + /// returns the reason in \p Info. + bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, + std::string &Info) const { + if (ComplexDeprecationInfo) + return ComplexDeprecationInfo(MI, STI, Info); + if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { + // FIXME: it would be nice to include the subtarget feature here. + Info = "deprecated"; + return true; + } + return false; + } + /// \brief Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; @@ -268,8 +287,20 @@ public: if (isBranch() || isCall() || isReturn() || isIndirectBranch()) return true; unsigned PC = RI.getProgramCounter(); - if (PC == 0) return false; - return hasDefOfPhysReg(MI, PC, RI); + if (PC == 0) + return false; + if (hasDefOfPhysReg(MI, PC, RI)) + return true; + // A variadic instruction may define PC in the variable operand list. + // There's currently no indication of which entries in a variable + // list are defs and which are uses. While that's the case, this function + // needs to assume they're defs in order to be conservatively correct. + for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { + if (MI.getOperand(i).isReg() && + RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) + return true; + } + return false; } /// \brief Return true if this instruction has a predicate operand diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 65d1559ac66a3..c4f9e1c32ab10 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -157,17 +157,12 @@ public: /// class. The latency is the maximum completion time for any stage /// in the itinerary. /// - /// InstrStages override the itinerary's MinLatency property. In fact, if the - /// stage latencies, which may be zero, are less than MinLatency, - /// getStageLatency returns a value less than MinLatency. - /// - /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0), - /// then it defaults to one cycle. + /// If no stages exist, it defaults to one cycle. 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 SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; + return 1; // Calculate the maximum completion time for any stage. unsigned Latency = 0, StartCycle = 0; @@ -176,7 +171,6 @@ public: Latency = std::max(Latency, StartCycle + IS->getCycles()); StartCycle += IS->getNextCycles(); } - return Latency; } diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h index 696436dffa6ec..71f01fab20648 100644 --- a/include/llvm/MC/MCMachOSymbolFlags.h +++ b/include/llvm/MC/MCMachOSymbolFlags.h @@ -19,9 +19,9 @@ // 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 . + /// MachOSymbolFlags - We store the value for the 'desc' symbol field in the + /// lowest 16 bits of the implementation defined flags. + enum MachOSymbolFlags { // See . SF_DescFlagsMask = 0xFFFF, // Reference type flags. diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3c9a588d04134..3ba6e651007c5 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MachO.h" #include namespace llvm { @@ -98,7 +98,7 @@ class MachObjectWriter : public MCObjectWriter { /// @{ llvm::DenseMap > Relocations; + std::vector > Relocations; llvm::DenseMap IndirectSymBase; /// @} @@ -155,9 +155,8 @@ public: bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & - ~object::mach::CTFM_ArchMask; - return CPUType == object::mach::CTM_ARM; + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~MachO::CPU_ARCH_MASK; + return CPUType == MachO::CPU_TYPE_ARM; } /// @} @@ -213,7 +212,7 @@ public: // these through in many cases. void addRelocation(const MCSectionData *SD, - object::macho::RelocationEntry &MRE) { + MachO::any_relocation_info &MRE) { Relocations[SD].push_back(MRE); } diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCModule.h index 755fa025fbc7b..63635c7478ce4 100644 --- a/include/llvm/MC/MCModule.h +++ b/include/llvm/MC/MCModule.h @@ -15,44 +15,119 @@ #ifndef LLVM_MC_MCMODULE_H #define LLVM_MC_MCMODULE_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { class MCAtom; +class MCBasicBlock; +class MCDataAtom; +class MCFunction; +class MCObjectDisassembler; +class MCTextAtom; -/// MCModule - This class represent a completely disassembled object file or -/// executable. It comprises a list of MCAtom's, and a branch target table. -/// Each atom represents a contiguous range of either instructions or data. +/// \brief A completely disassembled object file or executable. +/// It comprises a list of MCAtom's, each representing a contiguous range of +/// either instructions or data. +/// An MCModule is created using MCObjectDisassembler::buildModule. class MCModule { - /// AtomAllocationTracker - An MCModule owns its component MCAtom's, so it - /// must track them in order to ensure they are properly freed as atoms are - /// merged or otherwise manipulated. - SmallPtrSet AtomAllocationTracker; + /// \name Atom tracking + /// @{ - /// OffsetMap - Efficiently maps offset ranges to MCAtom's. - IntervalMap OffsetMap; - - /// BranchTargetMap - Maps offsets that are determined to be branches and - /// can be statically resolved to their target offsets. - DenseMap BranchTargetMap; + /// \brief Atoms in this module, sorted by begin address. + /// FIXME: This doesn't handle overlapping atoms (which happen when a basic + /// block starts in the middle of an instruction of another basic block.) + typedef std::vector AtomListTy; + AtomListTy Atoms; + // For access to map/remap. friend class MCAtom; - /// remap - Update the interval mapping for an MCAtom. + /// \brief Remap \p Atom to the given range, and update its Begin/End fields. + /// \param Atom An atom belonging to this module. + /// An atom should always use this method to update its bounds, because this + /// enables the owning MCModule to keep track of its atoms. void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); + /// \brief Insert an atom in the module, using its Begin and End addresses. + void map(MCAtom *NewAtom); + /// @} + + /// \name Basic block tracking + /// @{ + typedef std::vector BBsByAtomTy; + BBsByAtomTy BBsByAtom; + + // For access to basic block > atom tracking. + friend class MCBasicBlock; + friend class MCTextAtom; + + /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. + /// This is used to update succs/preds when \p Atom is split. + void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); + void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); + /// @} + + /// \name Function tracking + /// @{ + typedef std::vector FunctionListTy; + FunctionListTy Functions; + /// @} + + /// The address of the entrypoint function. + uint64_t Entrypoint; + + MCModule (const MCModule &) LLVM_DELETED_FUNCTION; + MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; + + // MCObjectDisassembler creates MCModules. + friend class MCObjectDisassembler; + public: - MCModule(IntervalMap::Allocator &A) : OffsetMap(A) { } + MCModule() : Entrypoint(0) { } + ~MCModule(); + + /// \name Create a new MCAtom covering the specified offset range. + /// @{ + MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); + MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); + /// @} + + /// \name Access to the owned atom list, ordered by begin address. + /// @{ + const MCAtom *findAtomContaining(uint64_t Addr) const; + MCAtom *findAtomContaining(uint64_t Addr); + const MCAtom *findFirstAtomAfter(uint64_t Addr) const; + MCAtom *findFirstAtomAfter(uint64_t Addr); + + typedef AtomListTy::const_iterator const_atom_iterator; + typedef AtomListTy:: iterator atom_iterator; + const_atom_iterator atom_begin() const { return Atoms.begin(); } + atom_iterator atom_begin() { return Atoms.begin(); } + const_atom_iterator atom_end() const { return Atoms.end(); } + atom_iterator atom_end() { return Atoms.end(); } + /// @} - /// createAtom - Creates a new MCAtom covering the specified offset range. - MCAtom *createAtom(MCAtom::AtomType Type, uint64_t Begin, uint64_t End); + /// \brief Create a new MCFunction. + MCFunction *createFunction(StringRef Name); + + /// \name Access to the owned function list. + /// @{ + typedef FunctionListTy::const_iterator const_func_iterator; + typedef FunctionListTy:: iterator func_iterator; + const_func_iterator func_begin() const { return Functions.begin(); } + func_iterator func_begin() { return Functions.begin(); } + const_func_iterator func_end() const { return Functions.end(); } + func_iterator func_end() { return Functions.end(); } + /// @} + + /// \brief Get the address of the entrypoint function, or 0 if there is none. + uint64_t getEntrypoint() const { return Entrypoint; } }; } #endif - diff --git a/include/llvm/MC/MCModuleYAML.h b/include/llvm/MC/MCModuleYAML.h new file mode 100644 index 0000000000000..281e3d8dc912b --- /dev/null +++ b/include/llvm/MC/MCModuleYAML.h @@ -0,0 +1,41 @@ +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of MCModule. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMODULEYAML_H +#define LLVM_MC_MCMODULEYAML_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCInstrInfo; +class MCRegisterInfo; + +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. +/// \returns The empty string on success, an error message on failure. +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +/// \brief Creates a new module and returns it in \p MCM. +/// \returns The empty string on success, an error message on failure. +StringRef yaml2mcmodule(OwningPtr &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h new file mode 100644 index 0000000000000..0d87d33bab985 --- /dev/null +++ b/include/llvm/MC/MCObjectDisassembler.h @@ -0,0 +1,175 @@ +//===-- llvm/MC/MCObjectDisassembler.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 MCObjectDisassembler class, which +// can be used to construct an MCModule and an MC CFG from an ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H +#define LLVM_MC_MCOBJECTDISASSEMBLER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryObject.h" +#include + +namespace llvm { + +namespace object { + class ObjectFile; + class MachOObjectFile; +} + +class MCBasicBlock; +class MCDisassembler; +class MCFunction; +class MCInstrAnalysis; +class MCModule; +class MCObjectSymbolizer; + +/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. +/// This class builds on MCDisassembler to disassemble whole sections, creating +/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data). +/// It can also be used to create a control flow graph consisting of MCFunctions +/// and MCBasicBlocks. +class MCObjectDisassembler { +public: + MCObjectDisassembler(const object::ObjectFile &Obj, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA); + virtual ~MCObjectDisassembler() {} + + /// \brief Build an MCModule, creating atoms and optionally functions. + /// \param withCFG Also build a CFG by adding MCFunctions to the Module. + /// If withCFG is false, the MCModule built only contains atoms, representing + /// what was found in the object file. If withCFG is true, MCFunctions are + /// created, containing MCBasicBlocks. All text atoms are split to form basic + /// block atoms, which then each back an MCBasicBlock. + MCModule *buildModule(bool withCFG = false); + + MCModule *buildEmptyModule(); + + typedef std::vector AddressSetTy; + /// \name Create a new MCFunction. + MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); + + /// \brief Set the region on which to fallback if disassembly was requested + /// somewhere not accessible in the object file. + /// This is used for dynamic disassembly (see RawMemoryObject). + void setFallbackRegion(OwningPtr &Region) { + FallbackRegion.reset(Region.take()); + } + + /// \brief Set the symbolizer to use to get information on external functions. + /// Note that this isn't used to do instruction-level symbolization (that is, + /// plugged into MCDisassembler), but to symbolize function call targets. + void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { + MOS = ObjectSymbolizer; + } + + /// \brief Get the effective address of the entrypoint, or 0 if there is none. + virtual uint64_t getEntrypoint(); + + /// \name Get the addresses of static constructors/destructors in the object. + /// The caller is expected to know how to interpret the addresses; + /// for example, Mach-O init functions expect 5 arguments, not for ELF. + /// The addresses are original object file load addresses, not effective. + /// @{ + virtual ArrayRef getStaticInitFunctions(); + virtual ArrayRef getStaticExitFunctions(); + /// @} + + /// \name Translation between effective and objectfile load address. + /// @{ + /// \brief Compute the effective load address, from an objectfile virtual + /// address. This is implemented in a format-specific way, to take into + /// account things like PIE/ASLR when doing dynamic disassembly. + /// For example, on Mach-O this would be done by adding the VM addr slide, + /// on glibc ELF by keeping a map between segment load addresses, filled + /// using dl_iterate_phdr, etc.. + /// In most static situations and in the default impl., this returns \p Addr. + virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); + + /// \brief Compute the original load address, as specified in the objectfile. + /// This is the inverse of getEffectiveLoadAddr. + virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); + /// @} + +protected: + const object::ObjectFile &Obj; + const MCDisassembler &Dis; + const MCInstrAnalysis &MIA; + MCObjectSymbolizer *MOS; + + /// \brief The fallback memory region, outside the object file. + OwningPtr FallbackRegion; + + /// \brief Return a memory region suitable for reading starting at \p Addr. + /// In most cases, this returns a StringRefMemoryObject backed by the + /// containing section. When no section was found, this returns the + /// FallbackRegion, if it is suitable. + /// If it is not, or if there is no fallback region, this returns 0. + MemoryObject *getRegionFor(uint64_t Addr); + +private: + /// \brief Fill \p Module by creating an atom for each section. + /// This could be made much smarter, using information like symbols, but also + /// format-specific features, like mach-o function_start or data_in_code LCs. + void buildSectionAtoms(MCModule *Module); + + /// \brief Enrich \p Module with a CFG consisting of MCFunctions. + /// \param Module An MCModule returned by buildModule, with no CFG. + /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom. + /// When the CFG is built, contiguous instructions that were previously in a + /// single MCTextAtom will be split in multiple basic block atoms. + void buildCFG(MCModule *Module); + + MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); +}; + +class MCMachOObjectDisassembler : public MCObjectDisassembler { + const object::MachOObjectFile &MOOF; + + uint64_t VMAddrSlide; + uint64_t HeaderLoadAddress; + + // __DATA;__mod_init_func support. + llvm::StringRef ModInitContents; + // __DATA;__mod_exit_func support. + llvm::StringRef ModExitContents; + +public: + /// \brief Construct a Mach-O specific object disassembler. + /// \param VMAddrSlide The virtual address slide applied by dyld. + /// \param HeaderLoadAddress The load address of the mach_header for this + /// object. + MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, + uint64_t HeaderLoadAddress); + +protected: + uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE; + uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE; + uint64_t getEntrypoint() LLVM_OVERRIDE; + + ArrayRef getStaticInitFunctions() LLVM_OVERRIDE; + ArrayRef getStaticExitFunctions() LLVM_OVERRIDE; +}; + +} + +#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index a5853b602c871..c48dcb021620d 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -125,6 +125,10 @@ protected: const MCSection *DwarfStrOffDWOSection; const MCSection *DwarfAddrSection; + /// Sections for newer gnu pubnames and pubtypes. + const MCSection *DwarfGnuPubNamesSection; + const MCSection *DwarfGnuPubTypesSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -138,6 +142,8 @@ protected: /// ELF and MachO only. const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// StackMap section. + const MCSection *StackMapSection; /// EHFrameSection - EH frame section. It is initialized on demand so it /// can be overwritten (with uniquing). @@ -223,6 +229,12 @@ public: const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfGnuPubNamesSection() const { + return DwarfGnuPubNamesSection; + } + const MCSection *getDwarfGnuPubTypesSection() const { + return DwarfGnuPubTypesSection; + } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } @@ -275,6 +287,8 @@ public: const MCSection *getTLSDataSection() const { return TLSDataSection; } const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + const MCSection *getStackMapSection() const { return StackMapSection; } + /// ELF specific sections. /// const MCSection *getDataRelSection() const { return DataRelSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 22a283986975d..56675443015eb 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -40,10 +40,11 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); protected: - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, + MCCodeEmitter *_Emitter); + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); @@ -78,8 +79,7 @@ public: virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); @@ -94,7 +94,7 @@ public: virtual void EmitBundleAlignMode(unsigned AlignPow2); virtual void EmitBundleLock(bool AlignToEnd); virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0); + virtual void EmitBytes(StringRef Data); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -102,6 +102,10 @@ public: virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, @@ -110,15 +114,9 @@ public: const MCSymbol *Label); virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() >= SK_ELFStreamer && S->getKind() <= SK_WinCOFFStreamer; - } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h new file mode 100644 index 0000000000000..64b932ebe4f9c --- /dev/null +++ b/include/llvm/MC/MCObjectSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===// +// +// 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 MCObjectSymbolizer class, an MCSymbolizer that is +// backed by an object::ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H +#define LLVM_MC_MCOBJECTSYMBOLIZER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/Object/ObjectFile.h" +#include + +namespace llvm { + +class MCExpr; +class MCInst; +class MCRelocationInfo; +class raw_ostream; + +/// \brief An ObjectFile-backed symbolizer. +class MCObjectSymbolizer : public MCSymbolizer { +protected: + const object::ObjectFile *Obj; + + // Map a load address to the first relocation that applies there. As far as I + // know, if there are several relocations at the exact same address, they are + // related and the others can be determined from the first that was found in + // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR + // relocation (referencing the minuend symbol) is followed by an UNSIGNED + // relocation (referencing the subtrahend symbol). + const object::RelocationRef *findRelocationAt(uint64_t Addr); + const object::SectionRef *findSectionContaining(uint64_t Addr); + + MCObjectSymbolizer(MCContext &Ctx, OwningPtr &RelInfo, + const object::ObjectFile *Obj); + +public: + /// \name Overridden MCSymbolizer methods: + /// @{ + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize); + + void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, uint64_t Address); + /// @} + + /// \brief Look for an external function symbol at \p Addr. + /// (References through the ELF PLT, Mach-O stubs, and similar). + /// \returns An MCExpr representing the external symbol, or 0 if not found. + virtual StringRef findExternalFunctionAt(uint64_t Addr); + + /// \brief Create an object symbolizer for \p Obj. + static MCObjectSymbolizer * + createObjectSymbolizer(MCContext &Ctx, OwningPtr &RelInfo, + const object::ObjectFile *Obj); + +private: + typedef DenseMap AddrToRelocMap; + typedef std::vector SortedSectionList; + SortedSectionList SortedSections; + AddrToRelocMap AddrToReloc; + + void buildSectionList(); + void buildRelocationByAddrMap(); +}; + +} + +#endif diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0dab31489fbb6..1b3ab577519ba 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -63,6 +63,7 @@ private: AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); }; } // end namespace llvm diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index dcc98863333bd..1d15534299949 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -47,7 +47,7 @@ public: } } InlineAsmIdentifierInfo; - virtual ~MCAsmParserSemaCallback(); + virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) = 0; diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index f5b4dddc5198a..3fa89c109c1c6 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -99,19 +99,15 @@ public: bool isAllocatable() const { return Allocatable; } }; -/// MCRegisterDesc - 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. +/// MCRegisterDesc - This record contains information about a particular +/// register. 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 MCRegisterDesc { uint32_t Name; // Printable name for the reg (for debugging) - uint32_t Overlaps; // Overlapping registers, described above uint32_t SubRegs; // Sub-register set, described above uint32_t SuperRegs; // Super-register set, described above @@ -148,6 +144,13 @@ public: bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array @@ -161,6 +164,8 @@ private: const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. unsigned NumSubRegIndices; // Number of subreg indices. const uint16_t *RegEncodingTable; // Pointer to array of register // encodings. @@ -226,7 +231,6 @@ public: // internal list pointers. friend class MCSubRegIterator; friend class MCSuperRegIterator; - friend class MCRegAliasIterator; friend class MCRegUnitIterator; friend class MCRegUnitRootIterator; @@ -241,6 +245,7 @@ public: const char *Strings, const uint16_t *SubIndices, unsigned NumIndices, + const SubRegCoveredBits *SubIdxRanges, const uint16_t *RET) { Desc = D; NumRegs = NR; @@ -254,6 +259,7 @@ public: NumRegUnits = NRU; SubRegIndices = SubIndices; NumSubRegIndices = NumIndices; + SubRegIdxRanges = SubIdxRanges; RegEncodingTable = RET; } @@ -332,6 +338,16 @@ public: /// otherwise. unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; + /// \brief Get the size of the bit range covered by a sub-register index. + /// If the index isn't continuous, return the sum of the sizes of its parts. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// \brief Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + /// \brief Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { @@ -421,30 +437,26 @@ public: // aliasing registers. Use these iterator classes to traverse the lists. /// MCSubRegIterator enumerates all sub-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); - ++*this; + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; } }; /// MCSuperRegIterator enumerates all super-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSuperRegIterator() {} + MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); - ++*this; - } -}; - -/// MCRegAliasIterator enumerates all registers aliasing Reg. -/// If IncludeSelf is set, Reg itself is included in the list. -class MCRegAliasIterator : public MCRegisterInfo::DiffListIterator { -public: - MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, - bool IncludeSelf) { - init(Reg, MCRI->DiffLists + MCRI->get(Reg).Overlaps); // Initially, the iterator points to Reg itself. if (!IncludeSelf) ++*this; @@ -478,6 +490,7 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { public: /// MCRegUnitIterator - Create an iterator that traverses the register units /// in Reg. + MCRegUnitIterator() {} MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { assert(Reg && "Null register has no regunits"); // Decode the RegUnits MCRegisterDesc field. @@ -502,9 +515,7 @@ public: // super-registers. All registers aliasing Unit can be visited like this: // // for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { -// unsigned Root = *RI; -// visit(Root); -// for (MCSuperRegIterator SI(Root, MCRI); SI.isValid(); ++SI) +// for (MCSuperRegIterator SI(*RI, MCRI, true); SI.isValid(); ++SI) // visit(*SI); // } @@ -513,6 +524,7 @@ class MCRegUnitRootIterator { uint16_t Reg0; uint16_t Reg1; public: + MCRegUnitRootIterator() : Reg0(0), Reg1(0) {} MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); Reg0 = MCRI->RegUnitRoots[RegUnit][0]; @@ -537,6 +549,68 @@ public: } }; +/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is +/// set, Reg itself is included in the list. This iterator does not guarantee +/// any ordering or that entries are unique. +class MCRegAliasIterator { +private: + unsigned Reg; + const MCRegisterInfo *MCRI; + bool IncludeSelf; + + MCRegUnitIterator RI; + MCRegUnitRootIterator RRI; + MCSuperRegIterator SI; +public: + MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) + : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { + + // Initialize the iterators. + for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { + for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { + for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { + if (!(!IncludeSelf && Reg == *SI)) + return; + } + } + } + } + + bool isValid() const { + return RI.isValid(); + } + + unsigned operator*() const { + assert (SI.isValid() && "Cannot dereference an invalid iterator."); + return *SI; + } + + void advance() { + // Assuming SI is valid. + ++SI; + if (SI.isValid()) return; + + ++RRI; + if (RRI.isValid()) { + SI = MCSuperRegIterator(*RRI, MCRI, true); + return; + } + + ++RI; + if (RI.isValid()) { + RRI = MCRegUnitRootIterator(*RI, MCRI); + SI = MCSuperRegIterator(*RRI, MCRI, true); + } + } + + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + do advance(); + while (!IncludeSelf && isValid() && *SI == Reg); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h new file mode 100644 index 0000000000000..9dab90099b7d1 --- /dev/null +++ b/include/llvm/MC/MCRelocationInfo.h @@ -0,0 +1,55 @@ +//==-- llvm/MC/MCRelocationInfo.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 MCRelocationInfo class, which provides methods to +// create MCExprs from relocations, either found in an object::ObjectFile +// (object::RelocationRef), or provided through the C API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCRELOCATIONINFO_H +#define LLVM_MC_MCRELOCATIONINFO_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +namespace object { +class RelocationRef; +} +class MCExpr; +class MCContext; + +/// \brief Create MCExprs from relocations found in an object file. +class MCRelocationInfo { + MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + +protected: + MCContext &Ctx; + +public: + MCRelocationInfo(MCContext &Ctx); + virtual ~MCRelocationInfo(); + + /// \brief Create an MCExpr for the relocation \p Rel. + /// \returns If possible, an MCExpr corresponding to Rel, else 0. + virtual const MCExpr *createExprForRelocation(object::RelocationRef Rel); + + /// \brief Create an MCExpr for the target-specific \p VariantKind. + /// The VariantKinds are defined in llvm-c/Disassembler.h. + /// Used by MCExternalSymbolizer. + /// \returns If possible, an MCExpr corresponding to VariantKind, else 0. + virtual const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind); +}; + +} + +#endif diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index defa299035433..6881e1d05ac3e 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -30,15 +30,18 @@ struct MCProcResourceDesc { unsigned NumUnits; // Number of resource of this kind unsigned SuperIdx; // Index of the resources kind that contains this kind. - // Buffered resources may be consumed at some indeterminate cycle after - // dispatch (e.g. for instructions that may issue out-of-order). Unbuffered - // resources always consume their resource some fixed number of cycles after - // dispatch (e.g. for instruction interlocking that may stall the pipeline). - bool IsBuffered; + // Number of resources that may be buffered. + // + // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at + // some indeterminate cycle after dispatch (e.g. for instructions that may + // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume + // their resource some fixed number of cycles after dispatch (e.g. for + // instruction interlocking that may stall the pipeline). + int BufferSize; bool operator==(const MCProcResourceDesc &Other) const { return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx - && IsBuffered == Other.IsBuffered; + && BufferSize == Other.BufferSize; } }; @@ -121,7 +124,7 @@ struct MCSchedClassDesc { /// microarchitecture to the scheduler in the form of properties. It also /// optionally refers to scheduler resource tables and itinerary /// tables. Scheduler resource tables model the latency and cost for each -/// instruction type. Itinerary tables are an independant mechanism that +/// instruction type. Itinerary tables are an independent mechanism that /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. @@ -134,28 +137,22 @@ public: unsigned IssueWidth; static const unsigned DefaultIssueWidth = 1; - // MinLatency is the minimum latency between a register write - // followed by a data dependent read. This determines which - // instructions may be scheduled in the same per-cycle group. This - // is distinct from *expected* latency, which determines the likely - // critical path but does not guarantee a pipeline - // hazard. MinLatency can always be overridden by the number of - // InstrStage cycles. + // MicroOpBufferSize is the number of micro-ops that the processor may buffer + // for out-of-order execution. // - // (-1) Standard in-order processor. - // Use InstrItinerary OperandCycles as MinLatency. - // If no OperandCycles exist, then use the cycle of the last InstrStage. + // "0" means operations that are not ready in this cycle are not considered + // for scheduling (they go in the pending queue). Latency is paramount. This + // may be more efficient if many instructions are pending in a schedule. // - // (0) Out-of-order processor, or in-order with bundled dependencies. - // RAW dependencies may be dispatched in the same cycle. - // Optional InstrItinerary OperandCycles provides expected latency. + // "1" means all instructions are considered for scheduling regardless of + // whether they are ready in this cycle. Latency still causes issue stalls, + // but we balance those stalls against other heuristics. // - // (>0) In-order processor with variable latencies. - // Use the greater of this value or the cycle of the last InstrStage. - // Optional InstrItinerary OperandCycles provides expected latency. - // TODO: can't yet specify both min and expected latency per operand. - int MinLatency; - static const int DefaultMinLatency = -1; + // "> 1" means the processor is out-of-order. This is a machine independent + // estimate of highly machine specific characteristics such are the register + // renaming pool and reorder buffer. + unsigned MicroOpBufferSize; + static const unsigned DefaultMicroOpBufferSize = 0; // LoadLatency is the expected latency of load instructions. // @@ -172,21 +169,13 @@ public: unsigned HighLatency; static const unsigned DefaultHighLatency = 10; - // ILPWindow is the number of cycles that the scheduler effectively ignores - // before attempting to hide latency. This should be zero for in-order cpus to - // always hide expected latency. For out-of-order cpus, it may be tweaked as - // desired to roughly approximate instruction buffers. The actual threshold is - // not very important for an OOO processor, as long as it isn't too high. A - // nonzero value helps avoid rescheduling to hide latency when its is fairly - // obviously useless and makes register pressure heuristics more effective. - unsigned ILPWindow; - static const unsigned DefaultILPWindow = 0; - // MispredictPenalty is the typical number of extra cycles the processor // takes to recover from a branch misprediction. unsigned MispredictPenalty; static const unsigned DefaultMispredictPenalty = 10; + bool CompleteModel; + private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; @@ -203,11 +192,11 @@ public: // initialized in this default ctor because some clients directly instantiate // MCSchedModel instead of using a generated itinerary. MCSchedModel(): IssueWidth(DefaultIssueWidth), - MinLatency(DefaultMinLatency), + MicroOpBufferSize(DefaultMicroOpBufferSize), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), - ILPWindow(DefaultILPWindow), MispredictPenalty(DefaultMispredictPenalty), + CompleteModel(true), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), InstrItineraries(0) { @@ -216,20 +205,24 @@ public: } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, - unsigned mp, unsigned pi, const MCProcResourceDesc *pr, + MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, + unsigned mp, bool cm, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), - SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), - InstrItineraries(ii) {} + IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), CompleteModel(cm), ProcID(pi), + ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), + NumSchedClasses(nsc), InstrItineraries(ii) {} unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. bool hasInstrSchedModel() const { return SchedClassTable; } + /// Return true if this machine model data for all instructions with a + /// scheduling class (itinerary class or SchedRW list). + bool isComplete() const { return CompleteModel; } + unsigned getNumProcResourceKinds() const { return NumProcResourceKinds; } diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 50e33a5b040af..45c84ae71eeb6 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -19,28 +19,47 @@ #include "llvm/Support/COFF.h" namespace llvm { +class MCSymbol; /// 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; + // FIXME: The following fields should not be mutable, but are for now so + // the asm parser can honor the .linkonce directive. + /// Characteristics - This is the Characteristics field of a section, - // drawn from the enums below. - unsigned Characteristics; + /// drawn from the enums below. + mutable unsigned Characteristics; + + /// The COMDAT symbol of this section. Only valid if this is a COMDAT + /// section. Two COMDAT sections are merged if they have the same + /// COMDAT symbol. + const MCSymbol *COMDATSymbol; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 - int Selection; + mutable int Selection; + + /// Assoc - This is name of the associated section, if it is a COMDAT + /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an + /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). + mutable const MCSectionCOFF *Assoc; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - int Selection, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), - Characteristics(Characteristics), Selection (Selection) { + const MCSymbol *COMDATSymbol, int Selection, + const MCSectionCOFF *Assoc, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), + Selection(Selection), Assoc(Assoc) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); + assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == + (Assoc != 0) && + "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -57,7 +76,10 @@ namespace llvm { return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } - int getSelection () const { return Selection; } + int getSelection() const { return Selection; } + const MCSectionCOFF *getAssocSection() const { return Assoc; } + + void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) const; virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index b68bd8596801a..d7e88ea561247 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -41,7 +41,7 @@ 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 { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // TypeAndAttributes bitmasks. SECTION_TYPE = 0x000000FFU, SECTION_ATTRIBUTES = 0xFFFFFF00U, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 2cab481c3d8d8..0b1fe6ec01291 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -24,683 +24,716 @@ #include namespace llvm { - class MCAsmBackend; - class MCCodeEmitter; - class MCContext; - class MCExpr; - class MCInst; - class MCInstPrinter; - class MCSection; - class MCSymbol; - class StringRef; - class Twine; - class raw_ostream; - class formatted_raw_ostream; - - typedef std::pair MCSectionSubPair; - - /// 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 { - public: - enum StreamerKind { - SK_AsmStreamer, - SK_NullStreamer, - SK_RecordStreamer, - - // MCObjectStreamer subclasses. - SK_ELFStreamer, - SK_ARMELFStreamer, - SK_MachOStreamer, - SK_PureStreamer, - SK_MipsELFStreamer, - SK_WinCOFFStreamer - }; - - private: - const StreamerKind Kind; - MCContext &Context; - - MCStreamer(const MCStreamer&) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer&) LLVM_DELETED_FUNCTION; - - bool EmitEHFrame; - bool EmitDebugFrame; - - std::vector FrameInfos; - MCDwarfFrameInfo *getCurrentFrameInfo(); - MCSymbol *EmitCFICommon(); - void EnsureValidFrame(); - - std::vector W64UnwindInfos; - MCWin64EHUnwindInfo *CurrentW64UnwindInfo; - void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); - void EnsureValidW64UnwindInfo(); - - MCSymbol* LastSymbol; - - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. - SmallVector, 4> SectionStack; - - bool AutoInitSections; - - protected: - MCStreamer(StreamerKind Kind, MCContext &Ctx); - - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr* Expr); - - void RecordProcStart(MCDwarfFrameInfo &Frame); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - void EmitFrames(bool usingCFI); - - MCWin64EHUnwindInfo *getCurrentW64UnwindInfo(){return CurrentW64UnwindInfo;} - void EmitW64Tables(); - - public: - virtual ~MCStreamer(); - - StreamerKind getKind() const { return Kind; } - - /// State management - /// - virtual void reset(); - - MCContext &getContext() const { return Context; } - - unsigned getNumFrameInfos() { - return FrameInfos.size(); - } +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCExpr; +class MCInst; +class MCInstPrinter; +class MCSection; +class MCStreamer; +class MCSymbol; +class StringRef; +class Twine; +class raw_ostream; +class formatted_raw_ostream; + +typedef std::pair MCSectionSubPair; + +/// Target specific streamer interface. This is used so that targets can +/// implement support for target specific assembly directives. +/// +/// If target foo wants to use this, it should implement 3 classes: +/// * FooTargetStreamer : public MCTargetStreamer +/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetELFStreamer : public FooTargetStreamer +/// +/// FooTargetStreamer should have a pure virtual method for each directive. For +/// example, for a ".bar symbol_name" directive, it should have +/// virtual emitBar(const MCSymbol &Symbol) = 0; +/// +/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// method. The assembly streamer just prints ".bar symbol_name". The object +/// streamer does whatever is needed to implement .bar in the object file. +/// +/// In the assembly printer and parser the target streamer can be used by +/// calling getTargetStreamer and casting it to FooTargetStreamer: +/// +/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); +/// FooTargetStreamer &ATS = static_cast(TS); +/// +/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* +/// be treated differently. Callers should always talk to a FooTargetStreamer. +class MCTargetStreamer { +protected: + MCStreamer *Streamer; + +public: + virtual ~MCTargetStreamer(); + void setStreamer(MCStreamer *S) { Streamer = S; } +}; + +// FIXME: declared here because it is used from +// lib/CodeGen/AsmPrinter/ARMException.cpp. +class ARMTargetStreamer : public MCTargetStreamer { + virtual void anchor(); +public: + virtual void emitFnStart() = 0; + virtual void emitFnEnd() = 0; + virtual void emitCantUnwind() = 0; + virtual void emitPersonality(const MCSymbol *Personality) = 0; + virtual void emitHandlerData() = 0; + virtual void emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset = 0) = 0; + virtual void emitPad(int64_t Offset) = 0; + virtual void emitRegSave(const SmallVectorImpl &RegList, + bool isVector) = 0; + + virtual void switchVendor(StringRef Vendor) = 0; + virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0; + virtual void emitFPU(unsigned FPU) = 0; + virtual void finishAttributeSection() = 0; +}; + +/// 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; + OwningPtr TargetStreamer; + + MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + + bool EmitEHFrame; + bool EmitDebugFrame; + + std::vector FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + MCSymbol *EmitCFICommon(); + void EnsureValidFrame(); + + std::vector W64UnwindInfos; + MCWin64EHUnwindInfo *CurrentW64UnwindInfo; + void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); + void EnsureValidW64UnwindInfo(); + + MCSymbol *LastSymbol; + + // SymbolOrdering - Tracks an index to represent the order + // a symbol was emitted in. Zero means we did not emit that symbol. + DenseMap SymbolOrdering; + + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector, 4> SectionStack; + + bool AutoInitSections; + +protected: + MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer); + + const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, + const MCSymbol *B); + + const MCExpr *ForceExpAbs(const MCExpr *Expr); + + void RecordProcStart(MCDwarfFrameInfo &Frame); + virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); + void RecordProcEnd(MCDwarfFrameInfo &Frame); + virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); + void EmitFrames(MCAsmBackend *MAB, bool usingCFI); + + MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { + return CurrentW64UnwindInfo; + } + void EmitW64Tables(); + + virtual void EmitRawTextImpl(StringRef String); + +public: + virtual ~MCStreamer(); + + /// State management + /// + virtual void reset(); - const MCDwarfFrameInfo &getFrameInfo(unsigned i) { - return FrameInfos[i]; - } + MCContext &getContext() const { return Context; } - ArrayRef getFrameInfos() { - return FrameInfos; - } + MCTargetStreamer &getTargetStreamer() { + assert(TargetStreamer); + return *TargetStreamer; + } - unsigned getNumW64UnwindInfos() { - return W64UnwindInfos.size(); - } + unsigned getNumFrameInfos() { return FrameInfos.size(); } - MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { - return *W64UnwindInfos[i]; - } + 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. - MCSectionSubPair getCurrentSection() const { - if (!SectionStack.empty()) - return SectionStack.back().first; - return MCSectionSubPair(); - } + ArrayRef getFrameInfos() const { return FrameInfos; } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. - MCSectionSubPair getPreviousSection() const { - if (!SectionStack.empty()) - return SectionStack.back().second; - return MCSectionSubPair(); - } + unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } - /// 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 *, const MCExpr *) = 0; - - /// pushSection - Save the current and previous section on the - /// section stack. - void PushSection() { - SectionStack.push_back(std::make_pair(getCurrentSection(), - getPreviousSection())); - } + MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { + return *W64UnwindInfos[i]; + } - /// 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; - MCSectionSubPair oldSection = SectionStack.pop_back_val().first; - MCSectionSubPair curSection = SectionStack.back().first; - - if (oldSection != curSection) - ChangeSection(curSection.first, curSection.second); - return true; - } + void generateCompactUnwindEncodings(MCAsmBackend *MAB); - bool SubSection(const MCExpr *Subsection) { - if (SectionStack.empty()) - return false; + /// @name Assembly File Formatting. + /// @{ - SwitchSection(SectionStack.back().first.first, Subsection); - return true; - } + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. + virtual bool isVerboseAsm() const { return false; } - /// 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, const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, - const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) - SectionStack.back().first = MCSectionSubPair(Section, Subsection); + /// 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. + MCSectionSubPair getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return MCSectionSubPair(); + } + + /// getPreviousSection - Return the previous section that the streamer is + /// emitting code to. + MCSectionSubPair getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return MCSectionSubPair(); + } + + /// GetSymbolOrder - Returns an index to represent the order + /// a symbol was emitted in. (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + + /// 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 *, const MCExpr *) = 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; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); + 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, const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } + } + + /// SwitchSectionNoChange - Set the current section where code is being + /// emitted to @p Section. This is required to update CurSection. This + /// version does not call ChangeSection. + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + } + + /// Initialize the streamer. + void InitStreamer() { + if (AutoInitSections) + InitSections(); + } + + /// Tell this MCStreamer to call InitSections upon initialization. + void setAutoInitSections(bool AutoInitSections) { + this->AutoInitSections = AutoInitSections; + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + + /// InitToTextSection - Create a text section and switch the streamer to it. + virtual void InitToTextSection() = 0; + + /// AssignSection - Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignSection(MCSymbol *Symbol, const MCSection *Section); - /// Initialize the streamer. - void InitStreamer() { - if (AutoInitSections) - InitSections(); - } + /// 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); - /// Tell this MCStreamer to call InitSections upon initialization. - void setAutoInitSections(bool AutoInitSections) { - this->AutoInitSections = AutoInitSections; - } + virtual void EmitDebugLabel(MCSymbol *Symbol); - /// InitSections - Create the default sections and set the initial one. - virtual void InitSections() = 0; - - /// InitToTextSection - Create a text section and switch the streamer to it. - virtual void InitToTextSection() = 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); - - virtual void EmitDebugLabel(MCSymbol *Symbol); - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - - /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker - /// options into the output. - virtual void EmitLinkerOptions(ArrayRef Kind) {} - - /// EmitDataRegion - Note in the output the specified region @p Kind. - virtual void EmitDataRegion(MCDataRegionType Kind) {} - - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; - - /// getOrCreateSymbolData - Get symbol data for given symbol. - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); - - /// 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; - - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. - /// - /// @param Symbol - Symbol the section relative realocation should point to. - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - - /// 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. - /// @param ByteAlignment - The alignment of the common symbol in bytes. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 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, - uint64_t 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 \p Data into the output. - /// - /// This is used to implement assembler directives such as .byte, .ascii, - /// etc. - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0) = 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, - unsigned AddrSpace) = 0; - - void EmitValue(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) = 0; - - virtual void EmitSLEB128Value(const MCExpr *Value) = 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 Padding = 0, - 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); - - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gpdword on - /// targets that support them. - virtual void EmitGPRel64Value(const MCExpr *Value); - - /// 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 = 0); - - /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience - /// function that just wraps EmitFill. - void EmitZeros(uint64_t NumBytes, unsigned AddrSpace = 0) { - EmitFill(NumBytes, 0, AddrSpace); - } + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// 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. - /// @return false on success, true if the offset was invalid. - virtual bool 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 Directory, - StringRef Filename, unsigned CUID = 0); - - /// 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, - StringRef FileName); - - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) = 0; - - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - } + /// EmitAssemblerFlag - Note in the output the specified @p Flag. + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); - virtual void EmitCFISections(bool EH, bool Debug); - void EmitCFIStartProc(); - void EmitCFIEndProc(); - virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual void EmitCFIDefCfaOffset(int64_t Offset); - virtual void EmitCFIDefCfaRegister(int64_t Register); - virtual void EmitCFIOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFIRememberState(); - virtual void EmitCFIRestoreState(); - virtual void EmitCFISameValue(int64_t Register); - virtual void EmitCFIRestore(int64_t Register); - virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitCFIEscape(StringRef Values); - virtual void EmitCFISignalFrame(); - virtual void EmitCFIUndefined(int64_t Register); - virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); - - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); - - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. - virtual void EmitInstruction(const MCInst &Inst) = 0; - - /// \brief Set the bundle alignment mode from now on in the section. - /// The argument is the power of 2 to which the alignment is set. The - /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; - - /// \brief The following instructions are a bundle-locked group. - /// - /// \param AlignToEnd - If true, the bundle-locked group will be aligned to - /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; - - /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 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); - - /// PPC-related methods. - /// FIXME: Eventually replace it with some "target MC streamer" and move - /// these methods there. - virtual void EmitTCEntry(const MCSymbol &S); - - /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; - /// Finish - Finish emission of machine code. - void Finish(); - }; - - /// 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 \p 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 \p 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, - bool useCFI, - bool useDwarfDirectory, - MCInstPrinter *InstPrint = 0, - MCCodeEmitter *CE = 0, - MCAsmBackend *TAB = 0, - bool ShowInst = false); - - /// createMachOStreamer - Create a machine code streamer which will generate - /// Mach-O format object files. - /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// options into the output. + virtual void EmitLinkerOptions(ArrayRef Kind) {} + + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; - /// createWinCOFFStreamer - Create a machine code streamer which will - /// generate Microsoft COFF format object files. + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + + /// 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. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createWinCOFFStreamer(MCContext &Ctx, - MCAsmBackend &TAB, - MCCodeEmitter &CE, raw_ostream &OS, - bool RelaxAll = false); + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - /// createELFStreamer - Create a machine code streamer which will generate - /// ELF format object files. - MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack); + /// 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 bool 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; - /// createPureStreamer - Create a machine code streamer which will generate - /// "pure" MC object files, for use with MC-JIT and testing tools. + /// EmitCOFFSymbolType - Emit the type of the symbol. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); + /// @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; + + /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// + /// @param Symbol - Symbol the section relative realocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); + + /// 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. + /// @param ByteAlignment - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 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, + uint64_t 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 \p Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data) = 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) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size); + + /// 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); + + /// 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); + + virtual void EmitULEB128Value(const MCExpr *Value) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value) = 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 Padding = 0); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value); + + /// EmitSymbolValue - Special case of EmitValue that avoids the client + /// having to pass in a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); + + /// EmitGPRel64Value - Emit the expression @p Value into the output as a + /// gprel64 (64-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gpdword on + /// targets that support them. + virtual void EmitGPRel64Value(const MCExpr *Value); + + /// 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); + + /// \brief Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + virtual void EmitZeros(uint64_t NumBytes); + + /// 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. + /// @return false on success, true if the offset was invalid. + virtual bool 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; + + /// Emit the "identifiers" directive. This implements the + /// '.ident "version foo"' assembler directive. + virtual void EmitIdent(StringRef IdentString) {} + + /// 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 Directory, + StringRef Filename, unsigned CUID = 0); + + /// 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, + StringRef FileName); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); + virtual void EmitCFISections(bool EH, bool Debug); + void EmitCFIStartProc(); + void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRestore(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFISignalFrame(); + virtual void EmitCFIUndefined(int64_t Register); + virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); + virtual void EmitCFIWindowSave(); + + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); + virtual void EmitWin64EHEndProc(); + virtual void EmitWin64EHStartChained(); + virtual void EmitWin64EHEndChained(); + virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, + bool Except); + virtual void EmitWin64EHHandlerData(); + virtual void EmitWin64EHPushReg(unsigned Register); + virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); + virtual void EmitWin64EHAllocStack(unsigned Size); + virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); + virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWin64EHPushFrame(bool Code); + virtual void EmitWin64EHEndProlog(); + + /// EmitInstruction - Emit the given @p Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// \brief Set the bundle alignment mode from now on in the section. + /// The argument is the power of 2 to which the alignment is set. The + /// value 0 means turn the bundle alignment off. + virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + + /// \brief The following instructions are a bundle-locked group. + /// + /// \param AlignToEnd - If true, the bundle-locked group will be aligned to + /// the end of a bundle. + virtual void EmitBundleLock(bool AlignToEnd) = 0; + + /// \brief Ends a bundle-locked group. + virtual void EmitBundleUnlock() = 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. + void EmitRawText(const Twine &String); + + /// Flush - Causes any cached state to be written out. + virtual void Flush() {} + + /// FinishImpl - Streamer specific finalization. + virtual void FinishImpl() = 0; + /// Finish - Finish emission of machine code. + void Finish(); +}; + +/// 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 \p 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 \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + formatted_raw_ostream &OS, bool isVerboseAsm, + bool useLoc, bool useCFI, bool useDwarfDirectory, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0, + bool ShowInst = false); + +/// createMachOStreamer - Create a machine code streamer which will generate +/// Mach-O format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &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 \p TAB and \p CE. +MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &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, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *CE, bool RelaxAll, + bool NoExecStack); + +/// createPureStreamer - Create a machine code streamer which will generate +/// "pure" MC object files, for use with MC-JIT and testing tools. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); } // end namespace llvm diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 346fb2df0ffc0..01e8236482f7a 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -72,6 +72,9 @@ public: /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); + /// InitCPUSchedModel - Recompute scheduling model based on CPU. + void InitCPUSchedModel(StringRef CPU); + /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. uint64_t ToggleFeature(uint64_t FB); diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h new file mode 100644 index 0000000000000..e42a2146dc539 --- /dev/null +++ b/include/llvm/MC/MCSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCSymbolizer.h - MCSymbolizer 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 MCSymbolizer class, which is used +// to symbolize instructions decoded from an object, that is, transform their +// immediate operands to MCExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOLIZER_H +#define LLVM_MC_MCSYMBOLIZER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCContext; +class MCInst; +class raw_ostream; + +/// \brief Symbolize and annotate disassembled instructions. +/// +/// For now this mimics the old symbolization logic (from both ARM and x86), that +/// relied on user-provided (C API) callbacks to do the actual symbol lookup in +/// the object file. This was moved to MCExternalSymbolizer. +/// A better API would not rely on actually calling the two methods here from +/// inside each disassembler, but would use the instr info to determine what +/// operands are actually symbolizable, and in what way. I don't think this +/// information exists right now. +class MCSymbolizer { + MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + +protected: + MCContext &Ctx; + OwningPtr RelInfo; + +public: + /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo. + MCSymbolizer(MCContext &Ctx, OwningPtr &RelInfo); + virtual ~MCSymbolizer(); + + /// \brief Try to add a symbolic operand instead of \p Value to the MCInst. + /// + /// Instead of having a difficult to read immediate, a symbolic operand would + /// represent this immediate in a more understandable way, for instance as a + /// symbol or an offset from a symbol. Relocations can also be used to enrich + /// the symbolic expression. + /// @param Inst - The MCInst where to insert the symbolic operand. + /// @param cStream - Stream to print comments and annotations on. + /// @param Value - Operand value, pc-adjusted by the caller if necessary. + /// @param Address - Load address of the instruction. + /// @param IsBranch - Is the instruction a branch? + /// @param Offset - Byte offset of the operand inside the inst. + /// @param InstSize - Size of the instruction in bytes. + /// @return Whether a symbolic operand was added. + virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize) = 0; + + /// \brief Try to add a comment on the PC-relative load. + /// For instance, in Mach-O, this is used to add annotations to instructions + /// that use C string literals, as found in __cstring. + virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) = 0; +}; + +} + +#endif diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 6e878df3cb1e0..d132a732c4163 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -11,6 +11,7 @@ #define LLVM_MC_TARGETPARSER_H #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCExpr.h" namespace llvm { class MCStreamer; @@ -143,7 +144,7 @@ public: /// mnemonicIsValid - This returns true if this is a valid mnemonic and false /// otherwise. - virtual bool mnemonicIsValid(StringRef Mnemonic) = 0; + virtual bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) = 0; /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. @@ -174,6 +175,14 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const SmallVectorImpl &Operands) = 0; + + virtual const MCExpr *applyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind, + MCContext &Ctx) { + return 0; + } + + virtual void onLabelParsed(MCSymbol *Symbol) { }; }; } // End llvm namespace diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index f13e7d5480267..213481c9090cf 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -17,6 +17,7 @@ namespace llvm { class raw_ostream; class MCWinCOFFObjectTargetWriter { + virtual void anchor(); const unsigned Machine; protected: diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index 83c8b72ee4a33..b3fbee77021d7 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -10,17 +10,15 @@ // 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 // explicitly passing an offset to the constructor. -// -// 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_MC_MACHINELOCATION_H #define LLVM_MC_MACHINELOCATION_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + namespace llvm { class MCSymbol; @@ -30,7 +28,7 @@ private: unsigned Register; // gcc/gdb register number. int Offset; // Displacement if not register. public: - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // 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 @@ -49,7 +47,8 @@ public: Offset == Other.Offset; } - // Accessors + // Accessors. + /// \return true iff this is a register-indirect location. bool isIndirect() const { return !IsRegister; } bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } @@ -74,30 +73,6 @@ public: 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/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 8862c8b762960..d0735ccd9fa31 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -37,9 +37,9 @@ struct SubtargetFeatureKV { uint64_t Value; // K-V integer value uint64_t Implies; // K-V bit mask - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -52,9 +52,9 @@ struct SubtargetInfoKV { const char *Key; // K-V key string const void *Value; // K-V pointer value - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -99,8 +99,7 @@ public: // Dump feature info. void dump() const; - /// Retrieve a formatted string of the default features for the specified - /// target triple. + /// Adds the default features for the specified target triple. void getDefaultSubtargetFeatures(const Triple& Triple); }; diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index e2478f6754b09..1cba51954eca2 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,12 +14,10 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { @@ -33,33 +31,17 @@ struct ArchiveMemberHeader { char Size[10]; ///< Size of data, not including header or padding. char Terminator[2]; - ///! Get the name without looking up long names. - llvm::StringRef getName() const { - char EndCond; - if (Name[0] == '/' || Name[0] == '#') - EndCond = ' '; - else - EndCond = '/'; - llvm::StringRef::size_type end = - llvm::StringRef(Name, sizeof(Name)).find(EndCond); - if (end == llvm::StringRef::npos) - end = sizeof(Name); - assert(end <= sizeof(Name) && end > 0); - // Don't include the EndCond if there is one. - return llvm::StringRef(Name, end); - } + /// Get the name without looking up long names. + llvm::StringRef getName() const; - uint64_t getSize() const { - uint64_t ret; - if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret)) - llvm_unreachable("Size is not an integer."); - return ret; - } -}; + /// Members are not larger than 4GB. + uint32_t getSize() const; -static const ArchiveMemberHeader *ToHeader(const char *base) { - return reinterpret_cast(base); -} + sys::fs::perms getAccessMode() const; + sys::TimeValue getLastModified() const; + unsigned getUID() const; + unsigned getGID() const; +}; class Archive : public Binary { virtual void anchor(); @@ -71,53 +53,34 @@ public: /// \brief Offset from Data to the start of the file. uint16_t StartOfFile; - public: - Child(const Archive *p, StringRef d) : Parent(p), Data(d) { - if (!p || d.empty()) - return; - // Setup StartOfFile and PaddingBytes. - StartOfFile = sizeof(ArchiveMemberHeader); - // Don't include attached name. - StringRef Name = ToHeader(Data.data())->getName(); - if (Name.startswith("#1/")) { - uint64_t NameSize; - if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) - llvm_unreachable("Long name length is not an integer"); - StartOfFile += NameSize; - } + const ArchiveMemberHeader *getHeader() const { + return reinterpret_cast(Data.data()); } + public: + Child(const Archive *Parent, const char *Start); + bool operator ==(const Child &other) const { - return (Parent == other.Parent) && (Data.begin() == other.Data.begin()); + assert(Parent == other.Parent); + return Data.begin() == other.Data.begin(); } bool operator <(const Child &other) const { return Data.begin() < other.Data.begin(); } - Child getNext() const { - size_t SpaceToSkip = Data.size(); - // If it's odd, add 1 to make it even. - if (SpaceToSkip & 1) - ++SpaceToSkip; - - const char *NextLoc = Data.data() + SpaceToSkip; - - // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data->getBufferEnd()) - return Child(Parent, StringRef(0, 0)); - - size_t NextSize = - sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize(); - - return Child(Parent, StringRef(NextLoc, NextSize)); - } + Child getNext() const; error_code getName(StringRef &Result) const; - int getLastModified() const; - int getUID() const; - int getGID() const; - int getAccessMode() const; + StringRef getRawName() const { return getHeader()->getName(); } + sys::TimeValue getLastModified() const { + return getHeader()->getLastModified(); + } + unsigned getUID() const { return getHeader()->getUID(); } + unsigned getGID() const { return getHeader()->getGID(); } + sys::fs::perms getAccessMode() const { + return getHeader()->getAccessMode(); + } /// \return the size of the archive member without the header or padding. uint64_t getSize() const { return Data.size() - StartOfFile; } @@ -126,16 +89,7 @@ public: } error_code getMemoryBuffer(OwningPtr &Result, - bool FullPath = false) const { - StringRef Name; - if (error_code ec = getName(Name)) - return ec; - SmallString<128> Path; - Result.reset(MemoryBuffer::getMemBuffer( - getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + - ")").toStringRef(Path) : Name, false)); - return error_code::success(); - } + bool FullPath = false) const; error_code getAsBinary(OwningPtr &Result) const; }; @@ -143,7 +97,7 @@ public: class child_iterator { Child child; public: - child_iterator() : child(Child(0, StringRef())) {} + child_iterator() : child(Child(0, 0)) {} child_iterator(const Child &c) : child(c) {} const Child* operator->() const { return &child; @@ -220,7 +174,7 @@ public: return Format; } - child_iterator begin_children(bool skip_internal = true) const; + child_iterator begin_children(bool SkipInternal = true) const; child_iterator end_children() const; symbol_iterator begin_symbols() const; @@ -234,9 +188,12 @@ public: // check if a symbol is in the archive child_iterator findSym(StringRef name) const; + bool hasSymbolTable() const; + private: child_iterator SymbolTable; child_iterator StringTable; + child_iterator FirstRegular; Kind Format; }; diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 78fcf6feb8519..a3f5625cc9b7f 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -38,6 +38,7 @@ protected: enum { ID_Archive, + ID_MachOUniversalBinary, // Object and children. ID_StartObjects, ID_COFF, @@ -87,6 +88,10 @@ public: return TypeID == ID_Archive; } + bool isMachOUniversalBinary() const { + return TypeID == ID_MachOUniversalBinary; + } + bool isELF() const { return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B; } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 6f42d76ee9960..e05ae6c654c74 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -23,6 +23,31 @@ namespace llvm { class ArrayRef; namespace object { +class ImportDirectoryEntryRef; +typedef content_iterator import_directory_iterator; + +/// The DOS compatible header at the front of all PE/COFF executables. +struct dos_header { + support::ulittle16_t Magic; + support::ulittle16_t UsedBytesInTheLastPage; + support::ulittle16_t FileSizeInPages; + support::ulittle16_t NumberOfRelocationItems; + support::ulittle16_t HeaderSizeInParagraphs; + support::ulittle16_t MinimumExtraParagraphs; + support::ulittle16_t MaximumExtraParagraphs; + support::ulittle16_t InitialRelativeSS; + support::ulittle16_t InitialSP; + support::ulittle16_t Checksum; + support::ulittle16_t InitialIP; + support::ulittle16_t InitialRelativeCS; + support::ulittle16_t AddressOfRelocationTable; + support::ulittle16_t OverlayNumber; + support::ulittle16_t Reserved[4]; + support::ulittle16_t OEMid; + support::ulittle16_t OEMinfo; + support::ulittle16_t Reserved2[10]; + support::ulittle32_t AddressOfNewExeHeader; +}; struct coff_file_header { support::ulittle16_t Machine; @@ -32,6 +57,104 @@ struct coff_file_header { support::ulittle32_t NumberOfSymbols; support::ulittle16_t SizeOfOptionalHeader; support::ulittle16_t Characteristics; + + bool isImportLibrary() const { return NumberOfSections == 0xffff; } +}; + +/// The 32-bit PE header that follows the COFF header. +struct pe32_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle32_t BaseOfData; + support::ulittle32_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle32_t SizeOfStackReserve; + support::ulittle32_t SizeOfStackCommit; + support::ulittle32_t SizeOfHeapReserve; + support::ulittle32_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +/// The 64-bit PE header that follows the COFF header. +struct pe32plus_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle64_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle64_t SizeOfStackReserve; + support::ulittle64_t SizeOfStackCommit; + support::ulittle64_t SizeOfHeapReserve; + support::ulittle64_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +struct data_directory { + support::ulittle32_t RelativeVirtualAddress; + support::ulittle32_t Size; +}; + +struct import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; +}; + +struct import_lookup_table_entry32 { + support::ulittle32_t data; + + bool isOrdinal() const { return data & 0x80000000; } + + uint16_t getOrdinal() const { + assert(isOrdinal() && "ILT entry is not an ordinal!"); + return data & 0xFFFF; + } + + uint32_t getHintNameRVA() const { + assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); + return data; + } }; struct coff_symbol { @@ -81,6 +204,12 @@ struct coff_relocation { support::ulittle16_t Type; }; +struct coff_aux_weak_external { + support::ulittle32_t TagIndex; + support::ulittle32_t Characteristics; + char Unused[10]; +}; + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -93,11 +222,16 @@ struct coff_aux_section_definition { class COFFObjectFile : public ObjectFile { private: - const coff_file_header *Header; + friend class ImportDirectoryEntryRef; + const coff_file_header *COFFHeader; + const pe32_header *PE32Header; + const data_directory *DataDirectory; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; uint32_t StringTableSize; + const import_directory_table_entry *ImportDirectory; + uint32_t NumberOfImportDirectory; error_code getString(uint32_t offset, StringRef &Res) const; @@ -105,13 +239,15 @@ private: const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; + error_code initSymbolTablePtr(); + error_code initImportTablePtr(); + protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -134,8 +270,8 @@ protected: bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -143,14 +279,11 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; @@ -173,13 +306,19 @@ public: const coff_section *getCOFFSection(section_iterator &It) const; const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; - + virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; virtual StringRef getLoadName() const; + import_directory_iterator import_directory_begin() const; + import_directory_iterator import_directory_end() const; + error_code getHeader(const coff_file_header *&Res) const; + error_code getCOFFHeader(const coff_file_header *&Res) const; + error_code getPE32Header(const pe32_header *&Res) const; + error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; error_code getSection(int32_t index, const coff_section *&Res) const; error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template @@ -196,12 +335,37 @@ public: error_code getSectionContents(const coff_section *Sec, ArrayRef &Res) const; + error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; -} -} +// The iterator for the import directory table. +class ImportDirectoryEntryRef { +public: + ImportDirectoryEntryRef() : OwningObject(0) {} + ImportDirectoryEntryRef(DataRefImpl ImportDirectory, + const COFFObjectFile *Owner) + : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} + + bool operator==(const ImportDirectoryEntryRef &Other) const; + error_code getNext(ImportDirectoryEntryRef &Result) const; + error_code getName(StringRef &Result) const; + + error_code + getImportTableEntry(const import_directory_table_entry *&Result) const; + + error_code + getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; + +private: + DataRefImpl ImportDirectoryPimpl; + const COFFObjectFile *OwningObject; +}; +} // end namespace object +} // end namespace llvm #endif diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h new file mode 100644 index 0000000000000..3fa3ec6c124b1 --- /dev/null +++ b/include/llvm/Object/COFFYAML.h @@ -0,0 +1,141 @@ +//===- COFFYAML.h - COFF YAMLIO 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 classes for handling the YAML representation of COFF. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFFYAML_H +#define LLVM_OBJECT_COFFYAML_H + +#include "llvm/Object/YAML.h" +#include "llvm/Support/COFF.h" + +namespace llvm { + +namespace COFF { +inline Characteristics operator|(Characteristics a, Characteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); +} + +inline SectionCharacteristics operator|(SectionCharacteristics a, + SectionCharacteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); +} +} + +// The structure of the yaml files is not an exact 1:1 match to COFF. In order +// to use yaml::IO, we use these structures which are closer to the source. +namespace COFFYAML { + struct Relocation { + uint32_t VirtualAddress; + uint16_t Type; + StringRef SymbolName; + }; + + struct Section { + COFF::section Header; + unsigned Alignment; + object::yaml::BinaryRef SectionData; + std::vector Relocations; + StringRef Name; + Section(); + }; + + struct Symbol { + COFF::symbol Header; + COFF::SymbolBaseType SimpleType; + COFF::SymbolComplexType ComplexType; + object::yaml::BinaryRef AuxiliaryData; + StringRef Name; + Symbol(); + }; + + struct Object { + COFF::header Header; + std::vector
    Sections; + std::vector Symbols; + Object(); + }; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::MachineTypes &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolBaseType &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolStorageClass &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolComplexType &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::Characteristics &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::SectionCharacteristics &Value); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Relocation &Rel); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFF::header &H); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Symbol &S); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Section &Sec); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Object &Obj); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index eb2390ab5d4cd..a6774c1150302 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -7,23 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file declares the ELFObjectFile template class. +// This file declares the ELFFile template class. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_ELF_H #define LLVM_OBJECT_ELF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include @@ -33,467 +36,26 @@ namespace llvm { namespace object { -using support::endianness; +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); -template -struct ELFType { - static const endianness TargetEndianness = target_endianness; - static const std::size_t MaxAlignment = max_alignment; - static const bool Is64Bits = is64Bits; -}; - -template -struct MaximumAlignment { - enum {value = AlignOf::Alignment > max_align ? max_align - : AlignOf::Alignment}; -}; - -// Subclasses of ELFObjectFile may need this for template instantiation +// Subclasses of ELFFile may need this for template instantiation inline 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]); + return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], + (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Half; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Word; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Xword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sxword; -}; - -template -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint32_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -/// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint64_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ -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; - -#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ - ELFT::Is64Bits) - -// Section header. -template -struct Elf_Shdr_Base; - -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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(TargetEndianness, MaxAlign, 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; - } -}; - -template -struct Elf_Sym_Base; - -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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(TargetEndianness, MaxAlign, 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); - } -}; - -/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section -/// (.gnu.version). This structure is identical for ELF32 and ELF64. -template -struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) -}; - -template -struct Elf_Verdaux_Impl; - -/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section -/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef Elf_Verdaux_Impl Elf_Verdaux; - Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) - Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) - Elf_Half vd_ndx; // Version index, used in .gnu.version entries - Elf_Half vd_cnt; // Number of Verdaux entries - Elf_Word vd_hash; // Hash of name - Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) - Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) - - /// Get the first Verdaux entry for this Verdef. - const Elf_Verdaux *getAux() const { - return reinterpret_cast((const char*)this + vd_aux); - } -}; - -/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef -/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vda_name; // Version name (offset in string table) - Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) -}; - -/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) - Elf_Half vn_cnt; // Number of associated Vernaux entries - Elf_Word vn_file; // Library name (string table offset) - Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) - Elf_Word vn_next; // Offset to next Verneed entry (in bytes) -}; - -/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template -struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vna_hash; // Hash of dependency name - Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) - Elf_Half vna_other; // Version index, used in .gnu.version entries - Elf_Word vna_name; // Dependency name - Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) -}; - -/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic -/// table section (.dynamic) look like. -template -struct Elf_Dyn_Base; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - } d_un; -}; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Sxword d_tag; - union { - Elf_Xword d_val; - Elf_Addr d_ptr; - } d_un; -}; - -/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template -struct Elf_Dyn_Impl : Elf_Dyn_Base { - using Elf_Dyn_Base::d_tag; - using Elf_Dyn_Base::d_un; - int64_t getTag() const { return d_tag; } - uint64_t getVal() const { return d_un.d_val; } - uint64_t getPtr() const { return d_un.ptr; } -}; - -// Elf_Rel: Elf Relocation -template -struct Elf_Rel_Base; - -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - - uint64_t getRInfo(bool isMips64EL) const { - uint64_t t = r_info; - if (!isMips64EL) - return t; - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed - // by a 32 bit big endian number. - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - return r_info; - } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; - } -}; - -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. - - uint64_t getRInfo(bool isMips64EL) const { - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed - // by a 32 bit big endian number. - uint64_t t = r_info; - if (!isMips64EL) - return t; - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; - } -}; - -template -struct Elf_Rel_Impl; - -template -struct Elf_Rel_Impl, isRela> - : Elf_Rel_Base, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - - // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, - // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) >> 32); - } - uint32_t getType(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL); - } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, uint32_t t) { - this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL)); - } -}; - -template -struct Elf_Rel_Impl, isRela> - : Elf_Rel_Base, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return this->getRInfo(isMips64EL) >> 8; - } - unsigned char getType(bool isMips64EL) const { - return (unsigned char) (this->getRInfo(isMips64EL) & 0x0ff); - } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - this->setRInfo((s << 8) + t); - } -}; - -template -struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - 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]; } -}; - -template -struct Elf_Phdr_Impl; - -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word p_type; // Type of segment - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Word p_flags; // Segment flags - Elf_Word p_align; // Segment alignment constraint -}; - -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word p_type; // Type of segment - Elf_Word p_flags; // Segment flags - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Xword p_align; // Segment alignment constraint -}; - -template -class ELFObjectFile : public ObjectFile { +template +class ELFFile { +public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef typename conditional::type uintX_t; -public: /// \brief Iterate over constant sized entities. - template + template class ELFEntityIterator { public: typedef ptrdiff_t difference_type; @@ -504,9 +66,8 @@ public: /// \brief Default construct iterator. ELFEntityIterator() : EntitySize(0), Current(0) {} - ELFEntityIterator(uint64_t EntSize, const char *Start) - : EntitySize(EntSize) - , Current(Start) {} + ELFEntityIterator(uintX_t EntSize, const char *Start) + : EntitySize(EntSize), Current(Start) {} reference operator *() { assert(Current && "Attempted to dereference an invalid iterator!"); @@ -546,14 +107,16 @@ public: difference_type operator -(const ELFEntityIterator &Other) const { assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitiySize!"); + "Subtracting iterators of different EntitySize!"); return (Current - Other.Current) / EntitySize; } const char *get() const { return Current; } + uintX_t getEntSize() const { return EntitySize; } + private: - uint64_t EntitySize; + uintX_t EntitySize; const char *Current; }; @@ -569,46 +132,141 @@ public: typedef Elf_Verneed_Impl Elf_Verneed; typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; - typedef ELFEntityIterator Elf_Dyn_iterator; - typedef ELFEntityIterator Elf_Sym_iterator; + typedef ELFEntityIterator Elf_Dyn_Iter; typedef ELFEntityIterator Elf_Rela_Iter; typedef ELFEntityIterator Elf_Rel_Iter; + typedef ELFEntityIterator Elf_Shdr_Iter; + + /// \brief Archive files are 2 byte aligned, so we need this for + /// PointerIntPair to work. + template + class ArchivePointerTypeTraits { + public: + static inline const void *getAsVoidPointer(T *P) { return P; } + static inline T *getFromVoidPointer(const void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 1 }; + }; + + class Elf_Sym_Iter { + public: + typedef ptrdiff_t difference_type; + typedef const Elf_Sym value_type; + typedef std::random_access_iterator_tag iterator_category; + typedef value_type &reference; + typedef value_type *pointer; + + /// \brief Default construct iterator. + Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} + Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) + : EntitySize(EntSize), Current(Start, IsDynamic) {} + + reference operator*() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return *reinterpret_cast(Current.getPointer()); + } + + pointer operator->() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return reinterpret_cast(Current.getPointer()); + } + + bool operator==(const Elf_Sym_Iter &Other) { + return Current == Other.Current; + } + + bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } + + Elf_Sym_Iter &operator++() { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize); + return *this; + } -protected: - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; + Elf_Sym_Iter operator++(int) { + Elf_Sym_Iter Tmp = *this; + ++*this; + return Tmp; + } + + Elf_Sym_Iter operator+(difference_type Dist) { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize * Dist); + return *this; + } + + Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { + EntitySize = Other.EntitySize; + Current = Other.Current; + return *this; + } + + difference_type operator-(const Elf_Sym_Iter &Other) const { + assert(EntitySize == Other.EntitySize && + "Subtracting iterators of different EntitySize!"); + return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; + } + + const char *get() const { return Current.getPointer(); } + + bool isDynamic() const { return Current.getInt(); } + + uintX_t getEntSize() const { return EntitySize; } + + private: + uintX_t EntitySize; + PointerIntPair > Current; + }; private: typedef SmallVector Sections_t; typedef DenseMap IndexMap_t; - typedef DenseMap > RelocMap_t; + + MemoryBuffer *Buf; + + const uint8_t *base() const { + return reinterpret_cast(Buf->getBufferStart()); + } 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. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + const Elf_Shdr *dot_symtab_sec; // Symbol table section. - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap ExtendedSymbolTable; + const Elf_Shdr *SymbolTableSectionHeaderIndex; + DenseMap ExtendedSymbolTable; - const Elf_Shdr *dot_dynamic_sec; // .dynamic const Elf_Shdr *dot_gnu_version_sec; // .gnu.version const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(0), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; + + DynRegionInfo DynamicRegion; + DynRegionInfo DynHashRegion; + DynRegionInfo DynStrRegion; + DynRegionInfo DynSymRegion; + // Pointer to SONAME entry in dynamic string table // This is set the first time getLoadName is called. mutable const char *dt_soname; -private: - uint64_t getROffset(DataRefImpl Rel) const; - // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -635,103 +293,29 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - - /// @brief Get the relocation section that contains \a Rel. - const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); - } - public: - bool isRelocationHasAddend(DataRefImpl Rel) const; - template - const T *getEntry(uint16_t Section, uint32_t Entry) const; template - const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint32_t index) const; - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; + const T *getEntry(uint32_t Section, uint32_t Entry) const; + template + const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Version, - bool &IsDefault) const; + const char *getDynamicString(uintX_t Offset) const; + ErrorOr getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *Symb, + bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; -protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? - void validateSymbol(DataRefImpl Symb) const; - StringRef getRelocationTypeName(uint32_t Type) const; + StringRef getRelocationTypeName(uint32_t Type) const; + void getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const; -public: - error_code getSymbolName(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Res) const; - error_code getSectionName(const Elf_Shdr *section, - StringRef &Res) const; - const Elf_Dyn *getDyn(DataRefImpl DynData) const; - error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; - uint64_t getSymbolIndex(const Elf_Sym *sym) const; -protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const; + /// \brief Get the symbol table section and symbol for a given relocation. + template + std::pair + getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFFile(MemoryBuffer *Object, error_code &ec); bool isMips64EL() const { return Header->e_machine == ELF::EM_MIPS && @@ -739,65 +323,51 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + Elf_Shdr_Iter begin_sections() const; + Elf_Shdr_Iter end_sections() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + Elf_Sym_Iter begin_symbols() const; + Elf_Sym_Iter end_symbols() const; - const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return SymbolTableSections[0]; - } - - const Elf_Shdr *getDynamicStringTableSectionHeader() const { - return dot_dynstr_sec; - } - - Elf_Dyn_iterator begin_dynamic_table() const; + Elf_Dyn_Iter begin_dynamic_table() const; /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. - Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; - - Elf_Sym_iterator begin_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, - (const char *)base() + DynSymtab->sh_offset); - return Elf_Sym_iterator(0, 0); + Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; + + Elf_Sym_Iter begin_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Sym_iterator end_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + - DynSymtab->sh_offset + DynSymtab->sh_size); - return Elf_Sym_iterator(0, 0); + Elf_Sym_Iter end_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, + (const char *)DynSymRegion.Addr + DynSymRegion.Size, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { + Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rela_Iter endELFRela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { + return Elf_Rela_Iter( + sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } - Elf_Rel_Iter beginELFRel(const Elf_Shdr *sec) const { + Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { return Elf_Rel_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rel_Iter endELFRel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { + return Elf_Rel_Iter(sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } /// \brief Iterate over program header table. @@ -815,36 +385,42 @@ public: (Header->e_phnum * Header->e_phentsize)); } - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; - virtual error_code getSectionContents(const Elf_Shdr *sec, - StringRef &Res) const; - uint64_t getNumSections() const; - uint64_t getStringTableIndex() const; + uintX_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; - const Elf_Ehdr *getElfHeader() const; + const Elf_Ehdr *getHeader() const { return Header; } const Elf_Shdr *getSection(const Elf_Sym *symb) const; - const Elf_Shdr *getElfSection(section_iterator &It) const; - const Elf_Sym *getElfSymbol(symbol_iterator &It) const; - const Elf_Sym *getElfSymbol(uint32_t index) const; - - // Methods for type inquiry through isa, cast, and dyn_cast - bool isDyldType() const { return isDyldELFObject; } - static inline bool classof(const Binary *v) { - return v->getType() == getELFType(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } + const Elf_Shdr *getSection(uint32_t Index) const; + const Elf_Sym *getSymbol(uint32_t index) const; + + ErrorOr getSymbolName(Elf_Sym_Iter Sym) const; + + /// \brief Get the name of \p Symb. + /// \param SymTab The symbol table section \p Symb is contained in. + /// \param Symb The symbol to get the name of. + /// + /// \p SymTab is used to lookup the string table to use to get the symbol's + /// name. + ErrorOr getSymbolName(const Elf_Shdr *SymTab, + const Elf_Sym *Symb) const; + ErrorOr getSectionName(const Elf_Shdr *Section) const; + uint64_t getSymbolIndex(const Elf_Sym *sym) const; + ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; + StringRef getLoadName() const; }; +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFFile > ELF32LEFile; +typedef ELFFile > ELF64LEFile; +typedef ELFFile > ELF32BEFile; +typedef ELFFile > ELF64BEFile; + // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template -void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { - unsigned vd_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::LoadVersionDefs(const Elf_Shdr *sec) const { + unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; const char *sec_end = sec_start + vd_size; @@ -859,7 +435,7 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { report_fatal_error("Unexpected verdef version"); size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vd); p += vd->vd_next; } @@ -867,11 +443,11 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template -void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { - unsigned vn_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::LoadVersionNeeds(const Elf_Shdr *sec) const { + unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries - const char *sec_start = (const char*)base() + sec->sh_offset; + const char *sec_start = (const char *)base() + sec->sh_offset; const char *sec_end = sec_start + vn_size; // The first Verneed entry is at the start of the section. const char *p = sec_start; @@ -891,7 +467,7 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { const Elf_Vernaux *vna = reinterpret_cast(paux); size_t index = vna->vna_other & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vna); paux += vna->vna_next; } @@ -899,10 +475,10 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { } } -template -void ELFObjectFile::LoadVersionMap() const { +template +void ELFFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) + if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -921,83 +497,16 @@ void ELFObjectFile::LoadVersionMap() const { LoadVersionNeeds(dot_gnu_version_r_sec); } -template -void ELFObjectFile::validateSymbol(DataRefImpl Symb) const { -#ifndef NDEBUG - 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!"); -#endif -} - -template -error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) 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. - // If the symbol table is .dynsym, we are iterating dynamic symbols, - // and there is only one table of these. - if (Symb.d.b != 0) { - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - } - // Otherwise return the terminator. - if (Symb.d.b == 0 || Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits::max(); - Symb.d.b = std::numeric_limits::max(); - } - } - - Result = SymbolRef(Symb, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); -} - -template -error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { - DataRefImpl Symb = SymRef.getRawDataRefImpl(); - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, - Version, IsDefault); -} - -template -ELF::Elf64_Word ELFObjectFile - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template +ELF::Elf64_Word ELFFile::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(const Elf_Sym *symb) const { +template +const typename ELFFile::Elf_Shdr * +ELFFile::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -1005,1202 +514,36 @@ ELFObjectFile::getSection(const Elf_Sym *symb) const { return getSection(symb->st_shndx); } -template -const typename ELFObjectFile::Elf_Ehdr * -ELFObjectFile::getElfHeader() const { - return Header; -} - -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getElfSection(section_iterator &It) const { - llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); - return reinterpret_cast(ShdrRef.p); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getElfSymbol(symbol_iterator &It) const { - return getSymbol(It->getRawDataRefImpl()); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getElfSymbol(uint32_t index) const { - DataRefImpl SymbolData; - SymbolData.d.a = index; - SymbolData.d.b = 1; - return getSymbol(SymbolData); -} - -template -error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = symb->st_value + - (Section ? Section->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template -error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch(Header->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - IsRelocatable = true; - } - Result = symb->st_value; - - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM) - Result &= ~1; - - if (IsRelocatable && Section != 0) - Result += Section->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template -error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { - uint32_t flags; - getSymbolFlags(Symb, flags); - if (flags & SymbolRef::SF_Common) { - uint64_t Value; - getSymbolValue(Symb, Value); - Res = Value; - } else { - Res = 0; - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_size == 0) - Result = UnknownAddressOrSize; - Result = symb->st_size; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb); - - 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 (getSymbolTableIndex(symb)) { - 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 (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - ret = 'w'; - else - if (symb->getType() == ELF::STT_OBJECT) - ret = 'V'; - else - ret = 'W'; - } - - if (ret == '?' && symb->getType() == ELF::STT_SECTION) { - StringRef name; - if (error_code ec = getSymbolName(Symb, name)) - return ec; - Result = StringSwitch(name) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n') - .Default('?'); - return object_error::success; - } - - Result = ret; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - switch (symb->getType()) { - case ELF::STT_NOTYPE: - Result = SymbolRef::ST_Unknown; - break; - case ELF::STT_SECTION: - Result = SymbolRef::ST_Debug; - break; - case ELF::STT_FILE: - Result = SymbolRef::ST_File; - break; - case ELF::STT_FUNC: - Result = SymbolRef::ST_Function; - break; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - Result = SymbolRef::ST_Data; - break; - default: - Result = SymbolRef::ST_Other; - break; - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = SymbolRef::SF_None; - - if (symb->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (symb->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (symb->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION) - Result |= SymbolRef::SF_FormatSpecific; - - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (symb->getType() == ELF::STT_COMMON || - getSymbolTableIndex(symb) == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (symb->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *sec = getSection(symb); - if (!sec) - Res = end_sections(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast(sec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - Val = symb->st_value; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, - SectionRef &Result) const { - const uint8_t *sec = reinterpret_cast(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast(sec); - Result = SectionRef(Sec, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_addr; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_size; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (const char*)base() + sec->sh_offset; - Result = StringRef(start, sec->sh_size); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { - const char *start = (const char*)base() + Sec->sh_offset; - Result = StringRef(start, Sec->sh_size); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_addralign; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionText(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_PROGBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionRequiredForExecution( - DataRefImpl Sec, bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_ALLOC) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - // For ELF, all zero-init sections are virtual (that is, they occupy no space - // in the object image) and vice versa. - Result = sec->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) - Result = false; - else - Result = true; - return object_error::success; -} - -template -error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const Elf_Sym *symb = getSymbol(Symb); - - unsigned shndx = symb->st_shndx; - bool Reserved = shndx >= ELF::SHN_LORESERVE - && shndx <= ELF::SHN_HIRESERVE; - - Result = !Reserved && (sec == getSection(symb->st_shndx)); - return object_error::success; -} - -template -relocation_iterator -ELFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; - } - return relocation_iterator(RelocationRef(RelData, this)); -} - -template -relocation_iterator -ELFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } - return relocation_iterator(RelocationRef(RelData, this)); -} - -// Relocations -template -error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } - Result = RelocationRef(Rel, this); - return object_error::success; +template +const typename ELFFile::Elf_Sym * +ELFFile::getSymbol(uint32_t Index) const { + return &*(begin_symbols() + Index); } -template -error_code ELFObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); - break; - } - } - DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); - SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && - "Only executable and shared objects files have addresses"); - Result = getROffset(Rel); - return object_error::success; -} - -template -error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { - assert(Header->e_type == ELF::ET_REL && - "Only relocatable object files have relocation offsets"); - Result = getROffset(Rel); - return object_error::success; -} - -template -uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: - return getRel(Rel)->r_offset; - case ELF::SHT_RELA: - return getRela(Rel)->r_offset; - } -} - -template -error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(isMips64EL()); - break; - } - } - return object_error::success; +template +ErrorOr > +ELFFile::getSectionContents(const Elf_Shdr *Sec) const { + if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + return object_error::parse_failed; + const uint8_t *Start = base() + Sec->sh_offset; + return ArrayRef(Start, Sec->sh_size); } -#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: Res = #enum; break; - -template -StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { - StringRef Res = "Unknown"; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); - default: break; - } - break; - case ELF::EM_386: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: break; - } - break; - case ELF::EM_MIPS: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); - default: break; - } - break; - case ELF::EM_AARCH64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); - default: break; - } - break; - case ELF::EM_ARM: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: break; - } - break; - case ELF::EM_HEXAGON: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: break; - } - break; - case ELF::EM_PPC: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); - default: break; - } - break; - case ELF::EM_PPC64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); - default: break; - } - break; - case ELF::EM_S390: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); - default: break; - } - break; - default: break; - } - return Res; +template +StringRef ELFFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(Header->e_machine, Type); } -#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME - -template -error_code ELFObjectFile::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint32_t type; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(isMips64EL()); - break; - } - } - +template +void ELFFile::getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const { if (!isMips64EL()) { - StringRef Name = getRelocationTypeName(type); + StringRef Name = getRelocationTypeName(Type); Result.append(Name.begin(), Name.end()); } else { - uint8_t Type1 = (type >> 0) & 0xFF; - uint8_t Type2 = (type >> 8) & 0xFF; - uint8_t Type3 = (type >> 16) & 0xFF; + uint8_t Type1 = (Type >> 0) & 0xFF; + uint8_t Type2 = (Type >> 8) & 0xFF; + uint8_t Type3 = (Type >> 16) & 0xFF; // Concat all three relocation type names. StringRef Name = getRelocationTypeName(Type1); @@ -2214,126 +557,63 @@ error_code ELFObjectFile::getRelocationTypeName( Result.append(1, '/'); Result.append(Name.begin(), Name.end()); } - - return object_error::success; } -template -error_code ELFObjectFile::getRelocationAdditionalInfo( - DataRefImpl Rel, int64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = 0; - return object_error::success; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->r_addend; - return object_error::success; - } - } -} - -template -error_code ELFObjectFile::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint8_t type; - StringRef res; - int64_t addend = 0; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(isMips64EL()); - symbol_index = getRel(Rel)->getSymbol(isMips64EL()); - // TODO: Read implicit addend from section data. - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = getEntry(sec->sh_link, symbol_index); - StringRef symname; - if (error_code ec = getSymbolName(getSection(sec->sh_link), symb, symname)) - return ec; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - default: - res = "Unknown"; - } - break; - case ELF::EM_AARCH64: - case ELF::EM_ARM: - case ELF::EM_HEXAGON: - res = symname; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; +template +template +std::pair::Elf_Shdr *, + const typename ELFFile::Elf_Sym *> +ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { + if (!Sec->sh_link) + return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0); + const Elf_Shdr *SymTable = getSection(Sec->sh_link); + return std::make_pair( + SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } // Verify that the last byte in the string table in a null. -template -void ELFObjectFile::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char*)base() + sh->sh_offset; +template +void ELFFile::VerifyStrTab(const Elf_Shdr *sh) const { + const char *strtab = (const char *)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType( - static_cast(ELFT::TargetEndianness) == support::little, - ELFT::Is64Bits), - Object) - , isDyldELFObject(false) - , SectionHeaderTable(0) - , dot_shstrtab_sec(0) - , dot_strtab_sec(0) - , dot_dynstr_sec(0) - , dot_dynamic_sec(0) - , dot_gnu_version_sec(0) - , dot_gnu_version_r_sec(0) - , dot_gnu_version_d_sec(0) - , dt_soname(0) - { - - const uint64_t FileSize = Data->getBufferSize(); +template +uint64_t ELFFile::getNumSections() const { + assert(Header && "Header not initialized!"); + if (Header->e_shnum == ELF::SHN_UNDEF) { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + return SectionHeaderTable->sh_size; + } + return Header->e_shnum; +} + +template +typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { + if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shstrndx == ELF::SHN_HIRESERVE) + return SectionHeaderTable->sh_link; + if (Header->e_shstrndx >= getNumSections()) + return 0; + } + return Header->e_shstrndx; +} + +template +ELFFile::ELFFile(MemoryBuffer *Object, error_code &ec) + : Buf(Object), + SectionHeaderTable(0), + dot_shstrtab_sec(0), + dot_strtab_sec(0), + dot_symtab_sec(0), + SymbolTableSectionHeaderIndex(0), + dot_gnu_version_sec(0), + dot_gnu_version_r_sec(0), + dot_gnu_version_d_sec(0), + dt_soname(0) { + const uint64_t FileSize = Buf->getBufferSize(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -2359,76 +639,64 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // 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_SYMTAB. - const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; - const Elf_Shdr* sh = SectionHeaderTable; - - // Reserve SymbolTableSections[0] for .dynsym - SymbolTableSections.push_back(NULL); + // Scan sections for special sections. - for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { - switch (sh->sh_type) { - case ELF::SHT_SYMTAB_SHNDX: { + for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); + SecI != SecE; ++SecI) { + switch (SecI->sh_type) { + case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) // FIXME: Proper error handling. report_fatal_error("More than one .symtab_shndx!"); - SymbolTableSectionHeaderIndex = sh; + SymbolTableSectionHeaderIndex = &*SecI; break; - } - case ELF::SHT_SYMTAB: { - SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); - SymbolTableSections.push_back(sh); + case ELF::SHT_SYMTAB: + if (dot_symtab_sec) + // FIXME: Proper error handling. + report_fatal_error("More than one .symtab!"); + dot_symtab_sec = &*SecI; + dot_strtab_sec = getSection(SecI->sh_link); break; - } case ELF::SHT_DYNSYM: { - if (SymbolTableSections[0] != NULL) + if (DynSymRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynsym!"); - SymbolTableSectionsIndexMap[i] = 0; - SymbolTableSections[0] = sh; - break; - } - case ELF::SHT_REL: - case ELF::SHT_RELA: { - SectionRelocMap[getSection(sh->sh_info)].push_back(i); + DynSymRegion.Addr = base() + SecI->sh_offset; + DynSymRegion.Size = SecI->sh_size; + DynSymRegion.EntSize = SecI->sh_entsize; + const Elf_Shdr *DynStr = getSection(SecI->sh_link); + DynStrRegion.Addr = base() + DynStr->sh_offset; + DynStrRegion.Size = DynStr->sh_size; + DynStrRegion.EntSize = DynStr->sh_entsize; break; } - case ELF::SHT_DYNAMIC: { - if (dot_dynamic_sec != NULL) + case ELF::SHT_DYNAMIC: + if (DynamicRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynamic!"); - dot_dynamic_sec = sh; + DynamicRegion.Addr = base() + SecI->sh_offset; + DynamicRegion.Size = SecI->sh_size; + DynamicRegion.EntSize = SecI->sh_entsize; break; - } - case ELF::SHT_GNU_versym: { + case ELF::SHT_GNU_versym: if (dot_gnu_version_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version section!"); - dot_gnu_version_sec = sh; + dot_gnu_version_sec = &*SecI; break; - } - case ELF::SHT_GNU_verdef: { + case ELF::SHT_GNU_verdef: if (dot_gnu_version_d_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_d section!"); - dot_gnu_version_d_sec = sh; + dot_gnu_version_d_sec = &*SecI; break; - } - case ELF::SHT_GNU_verneed: { + case ELF::SHT_GNU_verneed: if (dot_gnu_version_r_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_r section!"); - dot_gnu_version_r_sec = sh; + dot_gnu_version_r_sec = &*SecI; break; } - } - ++sh; - } - - // Sort section relocation lists by index. - for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), - e = SectionRelocMap.end(); i != e; ++i) { - std::sort(i->second.begin(), i->second.end()); } // Get string table sections. @@ -2438,162 +706,117 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) VerifyStrTab(dot_shstrtab_sec); } - // Merge this into the above loop. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + getNumSections() * 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; - VerifyStrTab(dot_strtab_sec); - } else if (SectionName == ".dynstr") { - if (dot_dynstr_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .dynstr!"); - dot_dynstr_sec = sh; - VerifyStrTab(dot_dynstr_sec); - } - } - } - // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { const Elf_Word *ShndxTable = reinterpret_cast(base() + SymbolTableSectionHeaderIndex->sh_offset); - error_code ec; - for (symbol_iterator si = begin_symbols(), - se = end_symbols(); si != se; si.increment(ec)) { - if (ec) - report_fatal_error("Fewer extended symbol table entries than symbols!"); + for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; + ++SI) { if (*ShndxTable != ELF::SHN_UNDEF) - ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ExtendedSymbolTable[&*SI] = *ShndxTable; ++ShndxTable; } } + + // Scan program headers. + for (Elf_Phdr_Iter PhdrI = begin_program_headers(), + PhdrE = end_program_headers(); + PhdrI != PhdrE; ++PhdrI) { + if (PhdrI->p_type == ELF::PT_DYNAMIC) { + DynamicRegion.Addr = base() + PhdrI->p_offset; + DynamicRegion.Size = PhdrI->p_filesz; + DynamicRegion.EntSize = sizeof(Elf_Dyn); + break; + } + } + + ec = error_code::success(); } // Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFObjectFile::getSymbolIndex(const Elf_Sym *Sym) const { - assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); - const Elf_Shdr *SymTab = *SymbolTableSections.begin(); +template +uint64_t ELFFile::getSymbolIndex(const Elf_Sym *Sym) const { uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); + uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % SymTab->sh_entsize == 0 && + assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && "Symbol not multiple of symbol size!"); - return SymOffset / SymTab->sh_entsize; + return SymOffset / dot_symtab_sec->sh_entsize; } -template -symbol_iterator ELFObjectFile::begin_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableSections.size() <= 1) { - 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 = 1; // The 0th table is .dynsym - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Shdr_Iter ELFFile::begin_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff); } -template -symbol_iterator ELFObjectFile::end_symbols() const { - DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Shdr_Iter ELFFile::end_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff + + (getNumSections() * Header->e_shentsize)); } -template -symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableSections[0] == NULL) { - 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; // The 0th table is .dynsym - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Sym_Iter ELFFile::begin_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset, false); } -template -symbol_iterator ELFObjectFile::end_dynamic_symbols() const { - DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Sym_Iter ELFFile::end_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset + + dot_symtab_sec->sh_size, + false); } -template -section_iterator ELFObjectFile::begin_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast(base() + Header->e_shoff); - return section_iterator(SectionRef(ret, this)); +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::begin_dynamic_table() const { + if (DynamicRegion.Addr) + return Elf_Dyn_Iter(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr); + return Elf_Dyn_Iter(0, 0); } -template -section_iterator ELFObjectFile::end_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast(base() - + Header->e_shoff - + (Header->e_shentsize*getNumSections())); - return section_iterator(SectionRef(ret, this)); -} +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::end_dynamic_table(bool NULLEnd) const { + if (!DynamicRegion.Addr) + return Elf_Dyn_Iter(0, 0); + Elf_Dyn_Iter Ret(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr + DynamicRegion.Size); -template -typename ELFObjectFile::Elf_Dyn_iterator -ELFObjectFile::begin_dynamic_table() const { - if (dot_dynamic_sec) - return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset); - return Elf_Dyn_iterator(0, 0); -} + if (NULLEnd) { + Elf_Dyn_Iter Start = begin_dynamic_table(); + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; -template -typename ELFObjectFile::Elf_Dyn_iterator -ELFObjectFile::end_dynamic_table(bool NULLEnd) const { - if (dot_dynamic_sec) { - Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset + - dot_dynamic_sec->sh_size); - - if (NULLEnd) { - Elf_Dyn_iterator Start = begin_dynamic_table(); - while (Start != Ret && Start->getTag() != ELF::DT_NULL) - ++Start; - - // Include the DT_NULL. - if (Start != Ret) - ++Start; - Ret = Start; - } - return Ret; + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; } - return Elf_Dyn_iterator(0, 0); + return Ret; } -template -StringRef ELFObjectFile::getLoadName() const { +template +StringRef ELFFile::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - Elf_Dyn_iterator it = begin_dynamic_table(); - Elf_Dyn_iterator ie = end_dynamic_table(); + Elf_Dyn_Iter it = begin_dynamic_table(); + Elf_Dyn_Iter ie = end_dynamic_table(); while (it != ie && it->getTag() != ELF::DT_SONAME) ++it; if (it != ie) { - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - dt_soname = getString(dot_dynstr_sec, it->getVal()); + dt_soname = getDynamicString(it->getVal()); } else { dt_soname = ""; } @@ -2601,207 +824,23 @@ StringRef ELFObjectFile::getLoadName() const { return dt_soname; } -template -library_iterator ELFObjectFile::begin_libraries_needed() const { - // Find the first DT_NEEDED entry - Elf_Dyn_iterator i = begin_dynamic_table(); - Elf_Dyn_iterator e = end_dynamic_table(); - while (i != e && i->getTag() != ELF::DT_NEEDED) - ++i; - - DataRefImpl DRI; - DRI.p = reinterpret_cast(i.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template -error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { - // Use the same DataRefImpl format as DynRef. - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast(Data.p)); - Elf_Dyn_iterator e = end_dynamic_table(); - - // Skip the current dynamic table entry and find the next DT_NEEDED entry. - do - ++i; - while (i != e && i->getTag() != ELF::DT_NEEDED); - - DataRefImpl DRI; - DRI.p = reinterpret_cast(i.get()); - Result = LibraryRef(DRI, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast(Data.p)); - if (i == end_dynamic_table()) - report_fatal_error("getLibraryPath() called on iterator end"); - - if (i->getTag() != ELF::DT_NEEDED) - report_fatal_error("Invalid library_iterator"); - - // This uses .dynstr to lookup the name of the DT_NEEDED entry. - // THis works as long as DT_STRTAB == .dynstr. This is true most of - // the time, but the specification allows exceptions. - // TODO: This should really use DT_STRTAB instead. Doing this requires - // reading the program headers. - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - Res = getString(dot_dynstr_sec, i->getVal()); - return object_error::success; -} - -template -library_iterator ELFObjectFile::end_libraries_needed() const { - Elf_Dyn_iterator e = end_dynamic_table(); - DataRefImpl DRI; - DRI.p = reinterpret_cast(e.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template -uint8_t ELFObjectFile::getBytesInAddress() const { - return ELFT::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"; - case ELF::EM_ARM: - return "ELF32-arm"; - case ELF::EM_HEXAGON: - return "ELF32-hexagon"; - case ELF::EM_MIPS: - return "ELF32-mips"; - 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"; - case ELF::EM_AARCH64: - return "ELF64-aarch64"; - case ELF::EM_PPC64: - return "ELF64-ppc64"; - case ELF::EM_S390: - return "ELF64-s390"; - 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; - case ELF::EM_AARCH64: - return Triple::aarch64; - case ELF::EM_ARM: - return Triple::arm; - case ELF::EM_HEXAGON: - return Triple::hexagon; - case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? - Triple::mipsel : Triple::mips; - case ELF::EM_PPC64: - return Triple::ppc64; - case ELF::EM_S390: - return Triple::systemz; - default: - return Triple::UnknownArch; - } -} - -template -uint64_t ELFObjectFile::getNumSections() const { - assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - return SectionHeaderTable->sh_size; - } - return Header->e_shnum; -} - -template -uint64_t -ELFObjectFile::getStringTableIndex() const { - if (Header->e_shnum == ELF::SHN_UNDEF) { - if (Header->e_shstrndx == ELF::SHN_HIRESERVE) - return SectionHeaderTable->sh_link; - if (Header->e_shstrndx >= getNumSections()) - return 0; - } - return Header->e_shstrndx; -} - -template -template -inline const T * -ELFObjectFile::getEntry(uint16_t Section, uint32_t Entry) const { +template +template +const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry(getSection(Section), Entry); } -template -template -inline const T * -ELFObjectFile::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { - return reinterpret_cast( - base() - + Section->sh_offset - + (Entry * Section->sh_entsize)); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getSymbol(DataRefImpl Symb) const { - return getEntry(SymbolTableSections[Symb.d.b], Symb.d.a); -} - -template -const typename ELFObjectFile::Elf_Rel * -ELFObjectFile::getRel(DataRefImpl Rel) const { - return getEntry(Rel.w.b, Rel.w.c); -} - -template -const typename ELFObjectFile::Elf_Rela * -ELFObjectFile::getRela(DataRefImpl Rela) const { - return getEntry(Rela.w.b, Rela.w.c); -} - -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 || sec->sh_type != ELF::SHT_DYNSYM) - // FIXME: Proper error handling. - report_fatal_error("Invalid symbol table section!"); - return sec; +template +template +const T *ELFFile::getEntry(const Elf_Shdr *Section, + uint32_t Entry) const { + return reinterpret_cast(base() + Section->sh_offset + + (Entry * Section->sh_entsize)); } -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint32_t index) const { +template +const typename ELFFile::Elf_Shdr * +ELFFile::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2813,15 +852,15 @@ ELFObjectFile::getSection(uint32_t index) const { + (index * Header->e_shentsize)); } -template -const char *ELFObjectFile::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template +const char *ELFFile::getString(uint32_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 { +template +const char *ELFFile::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. @@ -2829,55 +868,63 @@ const char *ELFObjectFile::getString(const Elf_Shdr *section, return (const char *)base() + section->sh_offset + offset; } -template -error_code ELFObjectFile::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { - if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb); - if (!section) - Result = ""; - else - Result = getString(dot_shstrtab_sec, section->sh_name); - return object_error::success; - } +template +const char *ELFFile::getDynamicString(uintX_t Offset) const { + if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) + return 0; + return (const char *)DynStrRegion.Addr + Offset; +} - if (section == SymbolTableSections[0]) { - // Symbol is in .dynsym, use .dynstr string table - Result = getString(dot_dynstr_sec, symb->st_name); - } else { - // Use the default symbol table name section. - Result = getString(dot_strtab_sec, symb->st_name); +template +ErrorOr ELFFile::getSymbolName(Elf_Sym_Iter Sym) const { + if (!Sym.isDynamic()) + return getSymbolName(dot_symtab_sec, &*Sym); + + if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(Sym->st_name)); +} + +template +ErrorOr ELFFile::getSymbolName(const Elf_Shdr *Section, + const Elf_Sym *Symb) const { + if (Symb->st_name == 0) { + const Elf_Shdr *ContainingSec = getSection(Symb); + if (ContainingSec) + return getSectionName(ContainingSec); } - return object_error::success; + + const Elf_Shdr *StrTab = getSection(Section->sh_link); + if (Symb->st_name >= StrTab->sh_size) + return object_error::parse_failed; + return StringRef(getString(StrTab, Symb->st_name)); } -template -error_code ELFObjectFile::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { - Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); - return object_error::success; +template +ErrorOr +ELFFile::getSectionName(const Elf_Shdr *Section) const { + if (Section->sh_name >= dot_shstrtab_sec->sh_size) + return object_error::parse_failed; + return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); } -template -error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template +ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != SymbolTableSections[0]) { + if (section != DynSymRegion.Addr && section != 0) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. - StringRef Name; - error_code ec = getSymbolName(section, symb, Name); - if (ec != object_error::success) - return ec; + ErrorOr SymName = getSymbolName(section, symb); + if (!SymName) + return SymName; + StringRef Name = *SymName; size_t atpos = Name.find('@'); if (atpos == StringRef::npos) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } ++atpos; if (atpos < Name.size() && Name[atpos] == '@') { @@ -2886,21 +933,19 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { IsDefault = false; } - Version = Name.substr(atpos); - return object_error::success; + return Name.substr(atpos); } // This is a dynamic symbol. Look in the GNU symbol version table. if (dot_gnu_version_sec == NULL) { // No version table. - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Determine the position in the symbol table of this entry. - const char *sec_start = (const char*)base() + section->sh_offset; - size_t entry_index = ((const char*)symb - sec_start)/section->sh_entsize; + size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / + DynSymRegion.EntSize; // Get the corresponding version index entry const Elf_Versym *vs = getEntry(dot_gnu_version_sec, entry_index); @@ -2909,16 +954,14 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, // Special markers for unversioned symbols. if (version_index == ELF::VER_NDX_LOCAL || version_index == ELF::VER_NDX_GLOBAL) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Lookup this symbol in the version table LoadVersionMap(); if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) - report_fatal_error("Symbol has version index without corresponding " - "define or reference entry"); + return object_error::parse_failed; const VersionMapEntry &entry = VersionMap[version_index]; // Get the version name string @@ -2929,7 +972,6 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { name_offset = entry.getVernaux()->vna_name; } - Version = getString(dot_dynstr_sec, name_offset); // Set IsDefault if (entry.isVerdef()) { @@ -2938,36 +980,9 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - return object_error::success; -} - -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - // Little-endian 32-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + if (name_offset >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(name_offset)); } /// This function returns the hash value for a symbol in the .dynsym section @@ -2984,8 +999,7 @@ static inline unsigned elf_hash(StringRef &symbolName) { } return h; } - -} -} +} // end namespace object +} // end namespace llvm #endif diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h new file mode 100644 index 0000000000000..962a3e2a8655b --- /dev/null +++ b/include/llvm/Object/ELFObjectFile.h @@ -0,0 +1,1027 @@ +//===- ELFObjectFile.h - 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 declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H +#define LLVM_OBJECT_ELF_OBJECT_FILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + +namespace llvm { +namespace object { + +template +class ELFObjectFile : public ObjectFile { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + typedef typename ELFFile::uintX_t uintX_t; + + typedef typename ELFFile::Elf_Sym Elf_Sym; + typedef typename ELFFile::Elf_Shdr Elf_Shdr; + typedef typename ELFFile::Elf_Rel Elf_Rel; + typedef typename ELFFile::Elf_Rela Elf_Rela; + typedef typename ELFFile::Elf_Dyn Elf_Dyn; + + typedef typename ELFFile::Elf_Sym_Iter Elf_Sym_Iter; + typedef typename ELFFile::Elf_Shdr_Iter Elf_Shdr_Iter; + typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; + +protected: + ELFFile EF; + + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + + virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; + + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const; + virtual error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const; + + uint64_t getROffset(DataRefImpl Rel) const; + StringRef getRelocationTypeName(uint32_t Type) const; + + /// \brief Get the relocation section that contains \a Rel. + const Elf_Shdr *getRelSection(DataRefImpl Rel) const { + return EF.getSection(Rel.d.a); + } + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + + Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const { + bool IsDynamic = Symb.p & 1; + if (IsDynamic) + return Elf_Sym_Iter( + EF.begin_dynamic_symbols().getEntSize(), + reinterpret_cast(Symb.p & ~uintptr_t(1)), IsDynamic); + return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), + reinterpret_cast(Symb.p), IsDynamic); + } + + DataRefImpl toDRI(Elf_Sym_Iter Symb) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Symb.get()) | + static_cast(Symb.isDynamic()); + return DRI; + } + + Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { + return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, + reinterpret_cast(Sec.p)); + } + + DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec.get()); + return DRI; + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec); + return DRI; + } + + Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { + return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), + reinterpret_cast(Dyn.p)); + } + + DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Dyn.get()); + return DRI; + } + + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +public: + ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + const Elf_Sym *getSymbol(DataRefImpl Symb) const; + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual StringRef getObjectType() const { return "ELF"; } + virtual unsigned getArch() const; + virtual StringRef getLoadName() const; + + const ELFFile *getELFFile() const { return &EF; } + + bool isDyldType() const { return isDyldELFObject; } + static inline bool classof(const Binary *v) { + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); + } +}; + +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFObjectFile > ELF32LEObjectFile; +typedef ELFObjectFile > ELF64LEObjectFile; +typedef ELFObjectFile > ELF32BEObjectFile; +typedef ELFObjectFile > ELF64BEObjectFile; + +template +error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { + DataRefImpl Symb = SymRef.getRawDataRefImpl(); + const Elf_Sym *symb = getSymbol(Symb); + ErrorOr Ver = + EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); + if (!Ver) + return Ver; + Version = *Ver; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + // Unintialized symbols have no offset in the object file + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + bool IsRelocatable; + switch (EF.getHeader()->e_type) { + case ELF::ET_EXEC: + case ELF::ET_DYN: + IsRelocatable = false; + break; + default: + IsRelocatable = true; + } + Result = ESym->st_value; + + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM) + Result &= ~1; + + if (IsRelocatable && ESec != 0) + Result += ESec->sh_addr; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + Elf_Sym_Iter Sym = toELFSymIter(Symb); + if (Sym->st_shndx == ELF::SHN_COMMON) + Res = Sym->st_value; + else + Res = 0; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { + Result = toELFSymIter(Symb)->st_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + switch (ESym->getType()) { + case ELF::STT_NOTYPE: + Result = SymbolRef::ST_Unknown; + break; + case ELF::STT_SECTION: + Result = SymbolRef::ST_Debug; + break; + case ELF::STT_FILE: + Result = SymbolRef::ST_File; + break; + case ELF::STT_FUNC: + Result = SymbolRef::ST_Function; + break; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + Result = SymbolRef::ST_Data; + break; + default: + Result = SymbolRef::ST_Other; + break; + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || + ESym == &*EF.begin_symbols()) + Result |= SymbolRef::SF_FormatSpecific; + + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || + EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (ESym->getType() == ELF::STT_TLS) + Result |= SymbolRef::SF_ThreadLocal; + + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec = EF.getSection(ESym); + if (!ESec) + Res = end_sections(); + else { + DataRefImpl Sec; + Sec.p = reinterpret_cast(ESec); + Res = section_iterator(SectionRef(Sec, this)); + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + const Elf_Sym *ESym = getSymbol(Symb); + Val = ESym->st_value; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addr; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addralign; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code +ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + return object_error::success; +} + +template +error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + Elf_Sym_Iter ESym = toELFSymIter(Symb); + + uintX_t Index = ESym->st_shndx; + bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); + return object_error::success; +} + +template +relocation_iterator +ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template +relocation_iterator +ELFObjectFile::section_rel_end(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + const Elf_Shdr *S = reinterpret_cast(Sec.p); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + RelData.d.b = 0; + else + RelData.d.b = S->sh_size / S->sh_entsize; + + return relocation_iterator(RelocationRef(RelData, this)); +} + +template +section_iterator +ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { + if (EF.getHeader()->e_type != ELF::ET_REL) + return end_sections(); + + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return end_sections(); + + const Elf_Shdr *R = EF.getSection(EShdr->sh_info); + return section_iterator(SectionRef(toDRI(R), this)); +} + +// Relocations +template +error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + ++Rel.d.b; + Result = RelocationRef(Rel, this); + return object_error::success; +} + +template +symbol_iterator +ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + break; + } + } + if (!symbolIdx) + return end_symbols(); + + const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); + + DataRefImpl SymbolData; + switch (SymSec->sh_type) { + default: + report_fatal_error("Invalid symbol table section type!"); + case ELF::SHT_SYMTAB: + SymbolData = toDRI(EF.begin_symbols() + symbolIdx); + break; + case ELF::SHT_DYNSYM: + SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx); + break; + } + + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template +error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template +uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; + } +} + +template +error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + return object_error::success; +} + +template +StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); +} + +template +error_code ELFObjectFile::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint32_t type; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + + EF.getRelocationTypeName(type, Result); + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationAddend(DataRefImpl Rel, + int64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = 0; + return object_error::success; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->r_addend; + return object_error::success; + } + } +} + +template +error_code ELFObjectFile::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint8_t type; + StringRef res; + int64_t addend = 0; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry(sec->sh_link, symbol_index); + ErrorOr SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName; + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + case ELF::R_X86_64_8: + case ELF::R_X86_64_16: + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + res = "Unknown"; + } + break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } + case ELF::EM_ARM: + case ELF::EM_HEXAGON: + res = *SymName; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template +const typename ELFFile::Elf_Sym * +ELFObjectFile::getSymbol(DataRefImpl Symb) const { + return &*toELFSymIter(Symb); +} + +template +const typename ELFObjectFile::Elf_Rel * +ELFObjectFile::getRel(DataRefImpl Rel) const { + return EF.template getEntry(Rel.d.a, Rel.d.b); +} + +template +const typename ELFObjectFile::Elf_Rela * +ELFObjectFile::getRela(DataRefImpl Rela) const { + return EF.template getEntry(Rela.d.a, Rela.d.b); +} + +template +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Object, ec) {} + +template +symbol_iterator ELFObjectFile::begin_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +} + +template +section_iterator ELFObjectFile::begin_sections() const { + return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); +} + +template +section_iterator ELFObjectFile::end_sections() const { + return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); +} + +template +StringRef ELFObjectFile::getLoadName() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + if (DI != DE) + return EF.getDynamicString(DI->getVal()); + return ""; +} + +template +library_iterator ELFObjectFile::begin_libraries_needed() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + return library_iterator(LibraryRef(toDRI(DI), this)); +} + +template +error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { + Elf_Dyn_Iter DI = toELFDynIter(Data); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + // Skip to the next DT_NEEDED entry. + do + ++DI; + while (DI != DE && DI->getTag() != ELF::DT_NEEDED); + + Result = LibraryRef(toDRI(DI), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); + return object_error::success; +} + +template +library_iterator ELFObjectFile::end_libraries_needed() const { + return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); +} + +template +uint8_t ELFObjectFile::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template +StringRef ELFObjectFile::getFileFormatName() const { + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF32-i386"; + case ELF::EM_X86_64: + return "ELF32-x86-64"; + case ELF::EM_ARM: + return "ELF32-arm"; + case ELF::EM_HEXAGON: + return "ELF32-hexagon"; + case ELF::EM_MIPS: + return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; + default: + return "ELF32-unknown"; + } + case ELF::ELFCLASS64: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF64-i386"; + case ELF::EM_X86_64: + return "ELF64-x86-64"; + case ELF::EM_AARCH64: + return "ELF64-aarch64"; + case ELF::EM_PPC64: + return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; + default: + return "ELF64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template +unsigned ELFObjectFile::getArch() const { + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: + return Triple::aarch64; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_HEXAGON: + return Triple::hexagon; + case ELF::EM_MIPS: + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel + : Triple::mips; + case ELF::EM_PPC64: + return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le + : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; + default: + return Triple::UnknownArch; + } +} + +/// FIXME: Maybe we should have a base ElfObjectFile that is not a template +/// and make these member functions? +static inline error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { + const ObjectFile *Obj = R.getObjectFile(); + DataRefImpl DRI = R.getRawDataRefImpl(); + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); +} + +/// This is a generic interface for retrieving GNU symbol version +/// information from an ELFObjectFile. +static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); +} +} +} + +#endif diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h new file mode 100644 index 0000000000000..84b603125a693 --- /dev/null +++ b/include/llvm/Object/ELFTypes.h @@ -0,0 +1,463 @@ +//===- ELFTypes.h - Endian specific types for ELF ---------------*- 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_ELF_TYPES_H +#define LLVM_OBJECT_ELF_TYPES_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace object { + +using support::endianness; + +template +struct ELFType { + static const endianness TargetEndianness = target_endianness; + static const std::size_t MaxAlignment = max_alignment; + static const bool Is64Bits = is64Bits; +}; + +template struct MaximumAlignment { + enum { value = AlignOf::Alignment > max_align ? max_align + : AlignOf::Alignment + }; +}; + +// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. +template +struct ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral< + uint16_t, target_endianness, + MaximumAlignment::value> Elf_Half; + typedef support::detail::packed_endian_specific_integral< + uint32_t, target_endianness, + MaximumAlignment::value> Elf_Word; + typedef support::detail::packed_endian_specific_integral< + int32_t, target_endianness, + MaximumAlignment::value> Elf_Sword; + typedef support::detail::packed_endian_specific_integral< + uint64_t, target_endianness, + MaximumAlignment::value> Elf_Xword; + typedef support::detail::packed_endian_specific_integral< + int64_t, target_endianness, + MaximumAlignment::value> Elf_Sxword; +}; + +template struct ELFDataTypeTypedefHelper; + +/// ELF 32bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint32_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +/// ELF 64bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint64_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +// I really don't like doing this, but the alternative is copypasta. +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +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; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. +template struct Elf_Shdr_Base; + +template +struct Elf_Shdr_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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(TargetEndianness, MaxAlign, 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; + } +}; + +template struct Elf_Sym_Base; + +template +struct Elf_Sym_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, 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(TargetEndianness, MaxAlign, 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); + } +}; + +/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section +/// (.gnu.version). This structure is identical for ELF32 and ELF64. +template +struct Elf_Versym_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) +}; + +template struct Elf_Verdaux_Impl; + +/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section +/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verdef_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef Elf_Verdaux_Impl Elf_Verdaux; + Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) + Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) + Elf_Half vd_ndx; // Version index, used in .gnu.version entries + Elf_Half vd_cnt; // Number of Verdaux entries + Elf_Word vd_hash; // Hash of name + Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) + Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) + + /// Get the first Verdaux entry for this Verdef. + const Elf_Verdaux *getAux() const { + return reinterpret_cast((const char *)this + vd_aux); + } +}; + +/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef +/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verdaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vda_name; // Version name (offset in string table) + Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) +}; + +/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verneed_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) + Elf_Half vn_cnt; // Number of associated Vernaux entries + Elf_Word vn_file; // Library name (string table offset) + Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) + Elf_Word vn_next; // Offset to next Verneed entry (in bytes) +}; + +/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template +struct Elf_Vernaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vna_hash; // Hash of dependency name + Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) + Elf_Half vna_other; // Version index, used in .gnu.version entries + Elf_Word vna_name; // Dependency name + Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) +}; + +/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic +/// table section (.dynamic) look like. +template struct Elf_Dyn_Base; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. +template +struct Elf_Dyn_Impl : Elf_Dyn_Base { + using Elf_Dyn_Base::d_tag; + using Elf_Dyn_Base::d_un; + int64_t getTag() const { return d_tag; } + uint64_t getVal() const { return d_un.d_val; } + uint64_t getPtr() const { return d_un.ptr; } +}; + +// Elf_Rel: Elf Relocation +template struct Elf_Rel_Base; + +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } +}; + +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + + uint64_t getRInfo(bool isMips64EL) const { + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + uint64_t t = r_info; + if (!isMips64EL) + return t; + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } +}; + +template struct Elf_Rel_Impl; + +template +struct Elf_Rel_Impl, + isRela> : Elf_Rel_Base< + ELFType, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) >> 32); + } + uint32_t getType(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); + } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, uint32_t t) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL)); + } +}; + +template +struct Elf_Rel_Impl, + isRela> : Elf_Rel_Base< + ELFType, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + unsigned char getType(bool isMips64EL) const { + return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); + } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, unsigned char t) { + this->setRInfo((s << 8) + t); + } +}; + +template +struct Elf_Ehdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + 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]; } +}; + +template struct Elf_Phdr_Impl; + +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word p_type; // Type of segment + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Word p_flags; // Segment flags + Elf_Word p_align; // Segment alignment constraint +}; + +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word p_type; // Type of segment + Elf_Word p_flags; // Segment flags + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Xword p_align; // Segment alignment constraint +}; + +} // end namespace object. +} // end namespace llvm. + +#endif diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h new file mode 100644 index 0000000000000..fca965f3dbf21 --- /dev/null +++ b/include/llvm/Object/ELFYAML.h @@ -0,0 +1,163 @@ +//===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of ELF. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELFYAML_H +#define LLVM_OBJECT_ELFYAML_H + +#include "llvm/Object/YAML.h" +#include "llvm/Support/ELF.h" + +namespace llvm { +namespace ELFYAML { + +// These types are invariant across 32/64-bit ELF, so for simplicity just +// directly give them their exact sizes. We don't need to worry about +// endianness because these are just the types in the YAMLIO structures, +// and are appropriately converted to the necessary endianness when +// reading/generating binary object files. +// The naming of these types is intended to be ELF_PREFIX, where PREFIX is +// the common prefix of the respective constants. E.g. ELF_EM corresponds +// to the `e_machine` constants, like `EM_X86_64`. +// In the future, these would probably be better suited by C++11 enum +// class's with appropriate fixed underlying type. +LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) +// Just use 64, since it can hold 32-bit values too. +LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) + +// For now, hardcode 64 bits everywhere that 32 or 64 would be needed +// since 64-bit can hold 32-bit values too. +struct FileHeader { + ELF_ELFCLASS Class; + ELF_ELFDATA Data; + ELF_ELFOSABI OSABI; + ELF_ET Type; + ELF_EM Machine; + llvm::yaml::Hex64 Entry; +}; +struct Symbol { + StringRef Name; + ELF_STT Type; + StringRef Section; + llvm::yaml::Hex64 Value; + llvm::yaml::Hex64 Size; +}; +struct LocalGlobalWeakSymbols { + std::vector Local; + std::vector Global; + std::vector Weak; +}; +struct Section { + StringRef Name; + ELF_SHT Type; + ELF_SHF Flags; + llvm::yaml::Hex64 Address; + object::yaml::BinaryRef Content; + StringRef Link; + llvm::yaml::Hex64 AddressAlign; +}; +struct Object { + FileHeader Header; + std::vector
    Sections; + // Although in reality the symbols reside in a section, it is a lot + // cleaner and nicer if we read them from the YAML as a separate + // top-level key, which automatically ensures that invariants like there + // being a single SHT_SYMTAB section are upheld. + LocalGlobalWeakSymbols Symbols; +}; + +} // end namespace ELFYAML +} // end namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Symbol &Symbol); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Section &Section); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Object &Object); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index fbaf71c17b8ef..8b0570b02f8b1 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -22,17 +22,17 @@ namespace object { const error_category &object_category(); struct object_error { -enum _ { - success = 0, - invalid_file_type, - parse_failed, - unexpected_eof -}; - _ v_; - - object_error(_ v) : v_(v) {} - explicit object_error(int v) : v_(_(v)) {} - operator int() const {return v_;} + enum Impl { + success = 0, + arch_not_found, + invalid_file_type, + parse_failed, + unexpected_eof + }; + Impl V; + + object_error(Impl V) : V(V) {} + operator Impl() const { return V; } }; inline error_code make_error_code(object_error e) { @@ -43,7 +43,8 @@ inline error_code make_error_code(object_error e) { template <> struct is_error_code_enum : true_type { }; -template <> struct is_error_code_enum : true_type { }; +template <> struct is_error_code_enum : true_type { +}; } // end namespace llvm. diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 14cd4d767d48a..100613ac8ccb5 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -17,19 +17,43 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/MachOFormat.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" -#include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { +/// DiceRef - This is a value type class that represents a single +/// data in code entry in the table in a Mach-O object file. +class DiceRef { + DataRefImpl DicePimpl; + const ObjectFile *OwningObject; + +public: + DiceRef() : OwningObject(NULL) { } + + DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); + + bool operator==(const DiceRef &Other) const; + bool operator<(const DiceRef &Other) const; + + error_code getNext(DiceRef &Result) const; + + error_code getOffset(uint32_t &Result) const; + error_code getLength(uint16_t &Result) const; + error_code getKind(uint16_t &Result) const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; +}; +typedef content_iterator dice_iterator; + class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { const char *Ptr; // Where in memory the load command is. - macho::LoadCommand C; // The command itself. + MachO::load_command C; // The command itself. }; MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, @@ -43,7 +67,6 @@ public: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; @@ -65,19 +88,17 @@ public: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; @@ -107,8 +128,11 @@ public: virtual StringRef getLoadName() const; - relocation_iterator getSectionRelBegin(unsigned Index) const; - relocation_iterator getSectionRelEnd(unsigned Index) const; + relocation_iterator section_rel_begin(unsigned Index) const; + relocation_iterator section_rel_end(unsigned Index) const; + + dice_iterator begin_dices() const; + dice_iterator end_dices() const; // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment @@ -121,53 +145,60 @@ public: ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; // MachO specific Info about relocations. - bool isRelocationScattered(const macho::RelocationEntry &RE) const; - unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; - bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; - bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; - uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; - SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; + bool isRelocationScattered(const MachO::any_relocation_info &RE) const; + unsigned getPlainRelocationSymbolNum( + const MachO::any_relocation_info &RE) const; + bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const; + bool getScatteredRelocationScattered( + const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationValue( + const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; + SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; // MachO specific structures. - macho::Section getSection(DataRefImpl DRI) const; - macho::Section64 getSection64(DataRefImpl DRI) const; - macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; - macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; - macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; - macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; - - macho::LinkeditDataLoadCommand + MachO::section getSection(DataRefImpl DRI) const; + MachO::section_64 getSection64(DataRefImpl DRI) const; + MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; + MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; + MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; + MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; + + MachO::linkedit_data_command getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; - macho::SegmentLoadCommand + MachO::segment_command getSegmentLoadCommand(const LoadCommandInfo &L) const; - macho::Segment64LoadCommand + MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - macho::LinkerOptionsLoadCommand + MachO::linker_options_command getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; - macho::RelocationEntry getRelocation(DataRefImpl Rel) const; - macho::Header getHeader() const; - macho::Header64Ext getHeader64Ext() const; - macho::IndirectSymbolTableEntry - getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; + MachO::data_in_code_entry getDice(DataRefImpl Rel) const; + MachO::mach_header getHeader() const; + MachO::mach_header_64 getHeader64() const; + uint32_t + getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, unsigned Index) const; - macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const; - macho::SymtabLoadCommand getSymtabLoadCommand() const; - macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + MachO::symtab_command getSymtabLoadCommand() const; + MachO::dysymtab_command getDysymtabLoadCommand() const; + MachO::linkedit_data_command getDataInCodeLoadCommand() const; StringRef getStringTableData() const; bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; + static Triple::ArchType getArch(uint32_t CPUType); + static bool classof(const Binary *v) { return v->isMachO(); } @@ -177,8 +208,66 @@ private: SectionList Sections; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; + const char *DataInCodeLoadCmd; }; +/// DiceRef +inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner) + : DicePimpl(DiceP) , OwningObject(Owner) {} + +inline bool DiceRef::operator==(const DiceRef &Other) const { + return DicePimpl == Other.DicePimpl; +} + +inline bool DiceRef::operator<(const DiceRef &Other) const { + return DicePimpl < Other.DicePimpl; +} + +inline error_code DiceRef::getNext(DiceRef &Result) const { + DataRefImpl Rel = DicePimpl; + const MachO::data_in_code_entry *P = + reinterpret_cast(Rel.p); + Rel.p = reinterpret_cast(P + 1); + Result = DiceRef(Rel, OwningObject); + return object_error::success; +} + +// Since a Mach-O data in code reference, a DiceRef, can only be created when +// the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for +// the methods that get the values of the fields of the reference. + +inline error_code DiceRef::getOffset(uint32_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.offset; + return object_error::success; +} + +inline error_code DiceRef::getLength(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.length; + return object_error::success; +} + +inline error_code DiceRef::getKind(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.kind; + return object_error::success; +} + +inline DataRefImpl DiceRef::getRawDataRefImpl() const { + return DicePimpl; +} + +inline const ObjectFile *DiceRef::getObjectFile() const { + return OwningObject; +} + } } diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h deleted file mode 100644 index ffca391ea2287..0000000000000 --- a/include/llvm/Object/MachOFormat.h +++ /dev/null @@ -1,415 +0,0 @@ -//===- 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, - CSARM_V7F = 10, - CSARM_V7S = 11, - CSARM_V7K = 12, - CSARM_V6M = 14, - CSARM_V7M = 15, - CSARM_V7EM = 16 - }; - - /// \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, - LinkeditLoadCommandSize = 16 - }; - - /// \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, - LCT_CodeSignature = 0x1d, - LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26, - LCT_DataInCode = 0x29, - LCT_LinkerOptions = 0x2D - }; - - /// \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; - }; - - struct LinkeditDataLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t DataOffset; - uint32_t DataSize; - }; - - struct LinkerOptionsLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t Count; - // Load command is followed by Count number of zero-terminated UTF8 strings, - // and then zero-filled to be 4-byte aligned. - }; - - /// @} - /// @name Section Data - /// @{ - - enum SectionFlags { - SF_PureInstructions = 0x80000000 - }; - - 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; - }; - // Despite containing a uint64_t, this structure is only 4-byte aligned within - // a MachO file. -#pragma pack(push) -#pragma pack(4) - struct Symbol64TableEntry { - uint32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - uint16_t Flags; - uint64_t Value; - }; -#pragma pack(pop) - - /// @} - /// @name Data-in-code Table Entry - /// @{ - - // See . - enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; - struct DataInCodeTableEntry { - uint32_t Offset; /* from mach_header to start of data region */ - uint16_t Length; /* number of bytes in data region */ - uint16_t Kind; /* a DataRegionType 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/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h new file mode 100644 index 0000000000000..c5d1359256b0e --- /dev/null +++ b/include/llvm/Object/MachOUniversal.h @@ -0,0 +1,102 @@ +//===- MachOUniversal.h - Mach-O universal binaries -------------*- 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 Mach-O fat/universal binaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H +#define LLVM_OBJECT_MACHOUNIVERSAL_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/MachO.h" + +namespace llvm { +namespace object { + +class ObjectFile; + +class MachOUniversalBinary : public Binary { + virtual void anchor(); + + uint32_t NumberOfObjects; +public: + class ObjectForArch { + const MachOUniversalBinary *Parent; + /// \brief Index of object in the universal binary. + uint32_t Index; + /// \brief Descriptor of the object. + MachO::fat_arch Header; + + public: + ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); + + void clear() { + Parent = 0; + Index = 0; + } + + bool operator==(const ObjectForArch &Other) const { + return (Parent == Other.Parent) && (Index == Other.Index); + } + + ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } + uint32_t getCPUType() const { return Header.cputype; } + + error_code getAsObjectFile(OwningPtr &Result) const; + }; + + class object_iterator { + ObjectForArch Obj; + public: + object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} + const ObjectForArch* operator->() const { + return &Obj; + } + + bool operator==(const object_iterator &Other) const { + return Obj == Other.Obj; + } + bool operator!=(const object_iterator &Other) const { + return !(*this == Other); + } + + object_iterator& operator++() { // Preincrement + Obj = Obj.getNext(); + return *this; + } + }; + + MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + + object_iterator begin_objects() const { + return ObjectForArch(this, 0); + } + object_iterator end_objects() const { + return ObjectForArch(0, 0); + } + + uint32_t getNumberOfObjects() const { return NumberOfObjects; } + + // Cast methods. + static inline bool classof(Binary const *V) { + return V->isMachOUniversalBinary(); + } + + error_code getObjectForArch(Triple::ArchType Arch, + OwningPtr &Result) const; +}; + +} +} + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index eb53cc0aab58e..9aea639ef0582 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -28,12 +28,8 @@ namespace object { class ObjectFile; union DataRefImpl { - struct { - // ELF needs this for relocations. This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - uint16_t a, b; - uint32_t c; - } w; + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. struct { uint32_t a, b; } d; @@ -89,6 +85,7 @@ inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { } class SymbolRef; +typedef content_iterator symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -107,7 +104,7 @@ public: error_code getAddress(uint64_t &Result) const; error_code getOffset(uint64_t &Result) const; - error_code getSymbol(SymbolRef &Result) const; + symbol_iterator getSymbol() const; error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing @@ -119,7 +116,6 @@ public: /// /// This is for display purposes only. error_code getTypeName(SmallVectorImpl &Result) const; - error_code getAdditionalInfo(int64_t &Result) const; /// @brief Get a string that represents the calculation of the value of this /// relocation. @@ -128,11 +124,14 @@ public: error_code getValueString(SmallVectorImpl &Result) const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; }; typedef content_iterator relocation_iterator; /// SectionRef - This is a value type class that represents a single section in /// the list of sections in the object file. +class SectionRef; +typedef content_iterator section_iterator; class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -169,10 +168,10 @@ public: relocation_iterator begin_relocations() const; relocation_iterator end_relocations() const; + section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator section_iterator; /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. @@ -193,7 +192,7 @@ public: ST_Other }; - enum Flags { + enum Flags LLVM_ENUM_INT_TYPE(unsigned) { SF_None = 0, SF_Undefined = 1U << 0, // Symbol is defined in another object file SF_Global = 1U << 1, // Global symbol @@ -222,10 +221,6 @@ public: error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; - /// Returns the ascii char that should be displayed in a symbol table dump via - /// nm for this symbol. - error_code getNMTypeChar(char &Result) const; - /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; @@ -238,7 +233,6 @@ public: DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator symbol_iterator; /// LibraryRef - This is a value type class that represents a single library in /// the list of libraries needed by a shared or dynamic object. @@ -298,7 +292,6 @@ protected: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -324,9 +317,9 @@ protected: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const = 0; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const = 0; - + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; @@ -336,14 +329,11 @@ protected: uint64_t &Res) const =0; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const =0; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const = 0; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const = 0; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const = 0; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const = 0; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const = 0; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { @@ -436,10 +426,6 @@ inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline error_code SymbolRef::getNMTypeChar(char &Result) const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); -} - inline error_code SymbolRef::getFlags(uint32_t &Result) const { return OwningObject->getSymbolFlags(SymbolPimpl, Result); } @@ -533,11 +519,15 @@ inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { } inline relocation_iterator SectionRef::begin_relocations() const { - return OwningObject->getSectionRelBegin(SectionPimpl); + return OwningObject->section_rel_begin(SectionPimpl); } inline relocation_iterator SectionRef::end_relocations() const { - return OwningObject->getSectionRelEnd(SectionPimpl); + return OwningObject->section_rel_end(SectionPimpl); +} + +inline section_iterator SectionRef::getRelocatedSection() const { + return OwningObject->getRelocatedSection(SectionPimpl); } inline DataRefImpl SectionRef::getRawDataRefImpl() const { @@ -566,8 +556,8 @@ inline error_code RelocationRef::getOffset(uint64_t &Result) const { return OwningObject->getRelocationOffset(RelocationPimpl, Result); } -inline error_code RelocationRef::getSymbol(SymbolRef &Result) const { - return OwningObject->getRelocationSymbol(RelocationPimpl, Result); +inline symbol_iterator RelocationRef::getSymbol() const { + return OwningObject->getRelocationSymbol(RelocationPimpl); } inline error_code RelocationRef::getType(uint64_t &Result) const { @@ -579,10 +569,6 @@ inline error_code RelocationRef::getTypeName(SmallVectorImpl &Result) return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const { - return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result); -} - inline error_code RelocationRef::getValueString(SmallVectorImpl &Result) const { return OwningObject->getRelocationValueString(RelocationPimpl, Result); @@ -596,6 +582,10 @@ inline DataRefImpl RelocationRef::getRawDataRefImpl() const { return RelocationPimpl; } +inline const ObjectFile *RelocationRef::getObjectFile() const { + return OwningObject; +} + // Inline function definitions. inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) : LibraryPimpl(LibraryP) diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 6239ec1796aec..97912fe52d819 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -80,6 +81,16 @@ public: switch (RelocType) { case llvm::ELF::R_PPC64_ADDR32: return visitELF_PPC64_ADDR32(R, Value); + case llvm::ELF::R_PPC64_ADDR64: + return visitELF_PPC64_ADDR64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-ppc") { + switch (RelocType) { + case llvm::ELF::R_PPC_ADDR32: + return visitELF_PPC_ADDR32(R, Value); default: HasError = true; return RelocToApply(); @@ -123,6 +134,37 @@ private: StringRef FileFormat; bool HasError; + int64_t getAddend32LE(RelocationRef R) { + const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64LE(RelocationRef R) { + const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend32BE(RelocationRef R) { + const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64BE(RelocationRef R) { + const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } /// Operations /// 386-ELF @@ -133,15 +175,13 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -152,35 +192,41 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } + + /// PPC32 ELF + RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -188,15 +234,14 @@ private: /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { int64_t Addend; - R.getAdditionalInfo(Addend); + getELFRelocationAddend(R, Addend); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -207,15 +252,13 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -226,8 +269,7 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); return RelocToApply(Value + Addend, 8); } }; diff --git a/include/llvm/Object/YAML.h b/include/llvm/Object/YAML.h new file mode 100644 index 0000000000000..89fe5047a86e9 --- /dev/null +++ b/include/llvm/Object/YAML.h @@ -0,0 +1,116 @@ +//===- YAML.h - YAMLIO utilities for object 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 declares utility classes for handling the YAML representation of +// object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_YAML_H +#define LLVM_OBJECT_YAML_H + +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace object { +namespace yaml { + +/// \brief Specialized YAMLIO scalar type for representing a binary blob. +/// +/// A typical use case would be to represent the content of a section in a +/// binary file. +/// This class has custom YAMLIO traits for convenient reading and writing. +/// It renders as a string of hex digits in a YAML file. +/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not +/// require the quotation marks, so for simplicity when outputting they are +/// omitted). +/// When reading, any string whose content is an even number of hex digits +/// will be accepted. +/// For example, all of the following are acceptable: +/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D') +/// +/// A significant advantage of using this class is that it never allocates +/// temporary strings or buffers for any of its functionality. +/// +/// Example: +/// +/// The YAML mapping: +/// \code +/// Foo: DEADBEEFCAFEBABE +/// \endcode +/// +/// Could be modeled in YAMLIO by the struct: +/// \code +/// struct FooHolder { +/// BinaryRef Foo; +/// }; +/// namespace llvm { +/// namespace yaml { +/// template <> +/// struct MappingTraits { +/// static void mapping(IO &IO, FooHolder &FH) { +/// IO.mapRequired("Foo", FH.Foo); +/// } +/// }; +/// } // end namespace yaml +/// } // end namespace llvm +/// \endcode +class BinaryRef { + friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); + /// \brief Either raw binary data, or a string of hex bytes (must always + /// be an even number of characters). + ArrayRef Data; + /// \brief Discriminator between the two states of the `Data` member. + bool DataIsHexString; + +public: + BinaryRef(ArrayRef Data) : Data(Data), DataIsHexString(false) {} + BinaryRef(StringRef Data) + : Data(reinterpret_cast(Data.data()), Data.size()), + DataIsHexString(true) {} + BinaryRef() : DataIsHexString(true) {} + /// \brief The number of bytes that are represented by this BinaryRef. + /// This is the number of bytes that writeAsBinary() will write. + ArrayRef::size_type binary_size() const { + if (DataIsHexString) + return Data.size() / 2; + return Data.size(); + } + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as binary to the given raw_ostream. + void writeAsBinary(raw_ostream &OS) const; + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as hex to the given raw_ostream. + /// + /// For example, a possible output could be `DEADBEEFCAFEBABE`. + void writeAsHex(raw_ostream &OS) const; +}; + +inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { + // Special case for default constructed BinaryRef. + if (LHS.Data.empty() && RHS.Data.empty()) + return true; + + return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; +} + +} +} + +namespace yaml { +template <> struct ScalarTraits { + static void output(const object::yaml::BinaryRef &, void *, + llvm::raw_ostream &); + static StringRef input(StringRef, void *, object::yaml::BinaryRef &); +}; +} + +} + +#endif diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index d3accfe7f1e02..06ba679c2b553 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -222,8 +222,17 @@ public: /// negation are present, the last one wins. bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; + /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative + /// form \p Neg, return true if the option or its alias is present, false if + /// the negation is present, and \p Default if none of the options are + /// given. If multiple options are present, the last one wins. + bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, + bool Default = true) const; + /// AddLastArg - Render only the last argument match \p Id0, if present. void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; + void AddLastArg(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const; /// AddAllArgs - Render all arguments matching the given ids. void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index e781fa02d75bc..963389f0bc6fd 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -14,10 +14,10 @@ // Define the kinds of options. -class OptionKind { +class OptionKind { string Name = name; // The kind precedence, kinds with lower precedence are matched first. - int Precedence = predecence; + int Precedence = precedence; // Indicate a sentinel option. bit Sentinel = sentinel; } @@ -44,6 +44,8 @@ def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">; // An option which is both joined to its (first) value, and followed by its // (second) value. def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">; +// An option which consumes all remaining arguments if there are any. +def KIND_REMAINING_ARGS : OptionKind<"RemainingArgs">; // Define the option flags. @@ -89,6 +91,7 @@ class Option prefixes, string name, OptionKind kind> { list Flags = []; OptionGroup Group = ?; Option Alias = ?; + list AliasArgs = []; } // Helpers for defining options. @@ -113,6 +116,7 @@ class JoinedAndSeparate prefixes, string name> // Mix-ins for adding optional attributes. class Alias