From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- .gitignore | 11 +- Android.mk | 4 +- CMakeLists.txt | 59 +- CODE_OWNERS.TXT | 48 +- README.txt | 4 +- autoconf/config.sub | 4 +- autoconf/configure.ac | 24 +- bindings/go/llvm/DIBuilderBindings.cpp | 165 +- bindings/go/llvm/DIBuilderBindings.h | 166 +- bindings/go/llvm/IRBindings.cpp | 56 +- bindings/go/llvm/IRBindings.h | 36 + bindings/go/llvm/InstrumentationBindings.cpp | 12 +- bindings/go/llvm/InstrumentationBindings.h | 4 +- bindings/go/llvm/SupportBindings.cpp | 1 - bindings/go/llvm/dibuilder.go | 129 +- bindings/go/llvm/executionengine.go | 36 +- bindings/go/llvm/executionengine_test.go | 7 +- bindings/go/llvm/ir.go | 58 +- bindings/go/llvm/linker.go | 11 +- bindings/go/llvm/transforms_instrumentation.go | 11 +- bindings/ocaml/CMakeLists.txt | 11 + bindings/ocaml/Makefile.ocaml | 29 +- bindings/ocaml/all_backends/CMakeLists.txt | 5 + bindings/ocaml/analysis/CMakeLists.txt | 5 + bindings/ocaml/backends/CMakeLists.txt | 27 + bindings/ocaml/bitreader/CMakeLists.txt | 5 + bindings/ocaml/bitwriter/CMakeLists.txt | 5 + bindings/ocaml/executionengine/CMakeLists.txt | 6 + .../ocaml/executionengine/executionengine_ocaml.c | 12 +- .../ocaml/executionengine/llvm_executionengine.ml | 22 +- .../ocaml/executionengine/llvm_executionengine.mli | 21 +- bindings/ocaml/irreader/CMakeLists.txt | 5 + bindings/ocaml/linker/CMakeLists.txt | 5 + bindings/ocaml/linker/linker_ocaml.c | 6 +- bindings/ocaml/linker/llvm_linker.ml | 8 +- bindings/ocaml/linker/llvm_linker.mli | 9 +- bindings/ocaml/llvm/CMakeLists.txt | 11 + bindings/ocaml/llvm/META.llvm.in | 8 + bindings/ocaml/llvm/Makefile | 2 +- bindings/ocaml/llvm/llvm.ml | 4 +- bindings/ocaml/llvm/llvm.mli | 12 +- bindings/ocaml/llvm/llvm_ocaml.c | 14 + bindings/ocaml/target/CMakeLists.txt | 5 + bindings/ocaml/transforms/CMakeLists.txt | 5 + bindings/ocaml/transforms/Makefile | 2 +- bindings/ocaml/transforms/ipo/CMakeLists.txt | 5 + .../transforms/passmgr_builder/CMakeLists.txt | 5 + .../ocaml/transforms/scalar_opts/CMakeLists.txt | 5 + bindings/ocaml/transforms/utils/CMakeLists.txt | 5 + bindings/ocaml/transforms/utils/Makefile | 19 + .../ocaml/transforms/utils/llvm_transform_utils.ml | 10 + .../transforms/utils/llvm_transform_utils.mli | 17 + .../ocaml/transforms/utils/transform_utils_ocaml.c | 31 + bindings/ocaml/transforms/vectorize/CMakeLists.txt | 5 + cmake/config-ix.cmake | 58 +- cmake/modules/AddLLVM.cmake | 101 +- cmake/modules/AddOCaml.cmake | 201 + cmake/modules/CMakeLists.txt | 2 +- cmake/modules/CheckAtomic.cmake | 10 +- cmake/modules/FindOCaml.cmake | 103 + cmake/modules/GetSVN.cmake | 80 +- cmake/modules/HandleLLVMOptions.cmake | 43 +- cmake/modules/LLVM-Config.cmake | 50 +- cmake/modules/LLVMConfig.cmake.in | 2 + cmake/modules/LLVMProcessSources.cmake | 33 +- cmake/modules/Makefile | 3 +- cmake/platforms/iOS.cmake | 26 +- configure | 209 +- docs/BitCodeFormat.rst | 12 +- docs/BitSets.rst | 70 + docs/CMake.rst | 46 +- docs/CMakeLists.txt | 43 + docs/CodeGenerator.rst | 12 +- docs/CodingStandards.rst | 19 +- docs/CommandGuide/lit.rst | 2 +- docs/CompilerWriterInfo.rst | 2 + docs/ExceptionHandling.rst | 176 +- docs/ExtendingLLVM.rst | 8 +- docs/GarbageCollection.rst | 607 +- docs/GettingStarted.rst | 4 +- docs/GettingStartedVS.rst | 4 +- docs/HowToSetUpLLVMStyleRTTI.rst | 26 +- docs/LangRef.rst | 589 +- docs/LinkTimeOptimization.rst | 2 +- docs/MergeFunctions.rst | 802 + docs/Passes.rst | 32 +- docs/Phabricator.rst | 3 +- docs/ProgrammersManual.rst | 75 +- docs/ReleaseNotes.rst | 28 +- docs/SourceLevelDebugging.rst | 1 - docs/StackMaps.rst | 7 + docs/Statepoints.rst | 580 + docs/TableGen/index.rst | 1 - docs/WritingAnLLVMPass.rst | 4 +- docs/conf.py | 4 +- docs/index.rst | 15 + docs/tutorial/LangImpl1.rst | 11 +- docs/tutorial/LangImpl4.rst | 2 +- docs/tutorial/LangImpl5.rst | 2 +- docs/tutorial/LangImpl6.rst | 2 +- docs/tutorial/LangImpl7.rst | 4 +- docs/tutorial/LangImpl8.rst | 716 +- docs/tutorial/LangImpl9.rst | 262 + examples/ExceptionDemo/ExceptionDemo.cpp | 41 +- examples/Kaleidoscope/CMakeLists.txt | 10 + examples/Kaleidoscope/Chapter2/CMakeLists.txt | 2 +- examples/Kaleidoscope/Chapter3/CMakeLists.txt | 2 +- examples/Kaleidoscope/Chapter4/CMakeLists.txt | 8 +- examples/Kaleidoscope/Chapter4/toy.cpp | 549 +- examples/Kaleidoscope/Chapter5/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter5/toy.cpp | 464 +- examples/Kaleidoscope/Chapter6/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter6/toy.cpp | 519 +- examples/Kaleidoscope/Chapter7/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter7/toy.cpp | 603 +- examples/Kaleidoscope/Chapter8/CMakeLists.txt | 13 + examples/Kaleidoscope/Chapter8/Makefile | 16 + examples/Kaleidoscope/Chapter8/toy.cpp | 1494 ++ examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp | 2 +- examples/Kaleidoscope/MCJIT/cached/toy.cpp | 252 +- examples/Kaleidoscope/MCJIT/complete/toy.cpp | 8 +- examples/Kaleidoscope/MCJIT/initial/toy.cpp | 250 +- examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp | 2 +- examples/Kaleidoscope/MCJIT/lazy/toy.cpp | 248 +- examples/Kaleidoscope/Makefile | 2 +- examples/Kaleidoscope/Orc/CMakeLists.txt | 4 + .../Kaleidoscope/Orc/fully_lazy/CMakeLists.txt | 13 + examples/Kaleidoscope/Orc/fully_lazy/Makefile | 17 + examples/Kaleidoscope/Orc/fully_lazy/README.txt | 21 + examples/Kaleidoscope/Orc/fully_lazy/toy.cpp | 1437 ++ examples/Kaleidoscope/Orc/initial/CMakeLists.txt | 12 + examples/Kaleidoscope/Orc/initial/Makefile | 17 + examples/Kaleidoscope/Orc/initial/README.txt | 13 + examples/Kaleidoscope/Orc/initial/toy.cpp | 1333 + .../Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt | 12 + examples/Kaleidoscope/Orc/lazy_codegen/Makefile | 17 + examples/Kaleidoscope/Orc/lazy_codegen/README.txt | 13 + examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp | 1338 + .../Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt | 12 + examples/Kaleidoscope/Orc/lazy_irgen/Makefile | 17 + examples/Kaleidoscope/Orc/lazy_irgen/README.txt | 16 + examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp | 1373 + include/llvm-c/Core.h | 5 +- include/llvm-c/ExecutionEngine.h | 4 + include/llvm-c/Linker.h | 9 +- include/llvm-c/Transforms/Scalar.h | 3 + include/llvm-c/lto.h | 48 +- include/llvm/ADT/APFloat.h | 2 +- include/llvm/ADT/APInt.h | 15 +- include/llvm/ADT/APSInt.h | 73 +- include/llvm/ADT/ArrayRef.h | 2 - include/llvm/ADT/BitVector.h | 42 +- include/llvm/ADT/DenseMap.h | 207 +- include/llvm/ADT/DenseSet.h | 35 +- include/llvm/ADT/DepthFirstIterator.h | 2 +- include/llvm/ADT/EquivalenceClasses.h | 3 +- include/llvm/ADT/FoldingSet.h | 74 +- include/llvm/ADT/Hashing.h | 104 - include/llvm/ADT/ImmutableList.h | 4 +- include/llvm/ADT/ImmutableMap.h | 4 +- include/llvm/ADT/ImmutableSet.h | 4 +- include/llvm/ADT/IntervalMap.h | 2 +- include/llvm/ADT/IntrusiveRefCntPtr.h | 6 +- include/llvm/ADT/MapVector.h | 9 + include/llvm/ADT/None.h | 5 +- include/llvm/ADT/Optional.h | 49 +- include/llvm/ADT/PointerUnion.h | 80 +- include/llvm/ADT/STLExtras.h | 280 +- include/llvm/ADT/ScopedHashTable.h | 4 +- include/llvm/ADT/SmallBitVector.h | 28 +- include/llvm/ADT/SmallPtrSet.h | 10 +- include/llvm/ADT/SmallVector.h | 53 +- include/llvm/ADT/SparseBitVector.h | 34 +- include/llvm/ADT/SparseMultiSet.h | 4 +- include/llvm/ADT/SparseSet.h | 4 +- include/llvm/ADT/StringMap.h | 15 +- include/llvm/ADT/StringRef.h | 7 + include/llvm/ADT/TinyPtrVector.h | 22 +- include/llvm/ADT/Triple.h | 55 +- include/llvm/ADT/Twine.h | 14 +- include/llvm/ADT/ilist.h | 12 +- include/llvm/ADT/iterator.h | 2 +- include/llvm/ADT/iterator_range.h | 1 - include/llvm/Analysis/AliasAnalysis.h | 27 +- include/llvm/Analysis/AliasSetTracker.h | 4 +- include/llvm/Analysis/AssumptionCache.h | 183 + include/llvm/Analysis/AssumptionTracker.h | 128 - include/llvm/Analysis/BranchProbabilityInfo.h | 4 + include/llvm/Analysis/CGSCCPassManager.h | 192 +- include/llvm/Analysis/CallGraph.h | 4 +- include/llvm/Analysis/CodeMetrics.h | 10 +- include/llvm/Analysis/DependenceAnalysis.h | 4 +- include/llvm/Analysis/FindUsedTypes.h | 66 - .../llvm/Analysis/FunctionTargetTransformInfo.h | 49 - include/llvm/Analysis/InlineCost.h | 10 +- include/llvm/Analysis/InstructionSimplify.h | 99 +- include/llvm/Analysis/JumpInstrTableInfo.h | 1 - include/llvm/Analysis/LazyCallGraph.h | 14 +- include/llvm/Analysis/LazyValueInfo.h | 29 +- include/llvm/Analysis/LibCallSemantics.h | 23 + include/llvm/Analysis/LoopAccessAnalysis.h | 290 + include/llvm/Analysis/LoopInfo.h | 202 +- include/llvm/Analysis/LoopInfoImpl.h | 19 + include/llvm/Analysis/MemoryDependenceAnalysis.h | 24 +- include/llvm/Analysis/PHITransAddr.h | 10 +- include/llvm/Analysis/Passes.h | 8 + include/llvm/Analysis/RegionInfo.h | 12 +- include/llvm/Analysis/RegionInfoImpl.h | 2 +- include/llvm/Analysis/ScalarEvolution.h | 30 +- include/llvm/Analysis/ScalarEvolutionExpressions.h | 2 +- include/llvm/Analysis/SparsePropagation.h | 4 +- include/llvm/Analysis/TargetLibraryInfo.h | 935 + include/llvm/Analysis/TargetTransformInfo.h | 637 +- include/llvm/Analysis/TargetTransformInfoImpl.h | 433 + include/llvm/Analysis/ValueTracking.h | 36 +- include/llvm/Bitcode/BitCodes.h | 2 +- include/llvm/Bitcode/BitcodeWriterPass.h | 2 +- include/llvm/Bitcode/BitstreamReader.h | 24 +- include/llvm/Bitcode/LLVMBitCodes.h | 41 +- include/llvm/Bitcode/ReaderWriter.h | 70 +- include/llvm/CodeGen/Analysis.h | 17 +- include/llvm/CodeGen/AsmPrinter.h | 54 +- include/llvm/CodeGen/BasicTTIImpl.h | 723 + include/llvm/CodeGen/CallingConvLower.h | 63 +- include/llvm/CodeGen/CommandFlags.h | 5 + include/llvm/CodeGen/DIE.h | 587 + include/llvm/CodeGen/FastISel.h | 11 +- include/llvm/CodeGen/ForwardControlFlowIntegrity.h | 1 - include/llvm/CodeGen/FunctionLoweringInfo.h | 16 +- include/llvm/CodeGen/GCMetadata.h | 295 +- include/llvm/CodeGen/GCMetadataPrinter.h | 76 +- include/llvm/CodeGen/GCStrategy.h | 254 +- include/llvm/CodeGen/GCs.h | 32 +- include/llvm/CodeGen/ISDOpcodes.h | 23 +- include/llvm/CodeGen/LexicalScopes.h | 18 +- include/llvm/CodeGen/LinkAllCodegenComponents.h | 1 + include/llvm/CodeGen/LiveInterval.h | 226 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 57 +- include/llvm/CodeGen/LiveIntervalUnion.h | 14 +- include/llvm/CodeGen/LivePhysRegs.h | 4 +- include/llvm/CodeGen/MachineDominanceFrontier.h | 4 +- include/llvm/CodeGen/MachineFrameInfo.h | 4 + include/llvm/CodeGen/MachineFunction.h | 22 +- include/llvm/CodeGen/MachineInstr.h | 25 +- include/llvm/CodeGen/MachineLoopInfo.h | 4 +- include/llvm/CodeGen/MachineModuleInfo.h | 37 +- include/llvm/CodeGen/MachinePassRegistry.h | 7 +- include/llvm/CodeGen/MachineRegisterInfo.h | 19 +- include/llvm/CodeGen/MachineSSAUpdater.h | 4 +- include/llvm/CodeGen/MachineScheduler.h | 1 - include/llvm/CodeGen/MachineValueType.h | 64 +- include/llvm/CodeGen/PBQP/Graph.h | 73 +- include/llvm/CodeGen/PBQP/ReductionRules.h | 32 +- include/llvm/CodeGen/Passes.h | 86 +- include/llvm/CodeGen/RegAllocPBQP.h | 132 +- include/llvm/CodeGen/ScheduleDAG.h | 6 + include/llvm/CodeGen/SelectionDAG.h | 14 +- include/llvm/CodeGen/SelectionDAGISel.h | 2 +- include/llvm/CodeGen/SelectionDAGNodes.h | 127 +- include/llvm/CodeGen/SlotIndexes.h | 2 +- include/llvm/CodeGen/StackMaps.h | 50 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 11 +- include/llvm/CodeGen/ValueTypes.td | 3 + include/llvm/CodeGen/VirtRegMap.h | 4 +- include/llvm/Config/config.h.cmake | 24 +- include/llvm/Config/config.h.in | 15 + include/llvm/Config/llvm-config.h.cmake | 7 +- include/llvm/Config/llvm-config.h.in | 3 + include/llvm/DebugInfo/DIContext.h | 151 - include/llvm/DebugInfo/DWARF/DIContext.h | 150 + .../DebugInfo/DWARF/DWARFAbbreviationDeclaration.h | 60 + .../llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h | 49 + include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h | 31 + include/llvm/DebugInfo/DWARF/DWARFContext.h | 292 + include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h | 63 + include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h | 70 + include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h | 87 + include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 43 + include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h | 160 + include/llvm/DebugInfo/DWARF/DWARFDebugLine.h | 238 + include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h | 81 + include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h | 77 + include/llvm/DebugInfo/DWARF/DWARFFormValue.h | 93 + include/llvm/DebugInfo/DWARF/DWARFRelocMap.h | 22 + include/llvm/DebugInfo/DWARF/DWARFSection.h | 24 + include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h | 38 + include/llvm/DebugInfo/DWARF/DWARFUnit.h | 285 + include/llvm/DebugInfo/DWARFFormValue.h | 93 - .../llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h | 59 + include/llvm/DebugInfo/PDB/DIA/DIADataStream.h | 33 + .../llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h | 35 + .../llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h | 35 + .../llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h | 37 + include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h | 37 + include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h | 39 + include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h | 206 + include/llvm/DebugInfo/PDB/DIA/DIASession.h | 42 + include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h | 36 + include/llvm/DebugInfo/PDB/DIA/DIASupport.h | 33 + include/llvm/DebugInfo/PDB/IPDBDataStream.h | 37 + include/llvm/DebugInfo/PDB/IPDBEnumChildren.h | 33 + include/llvm/DebugInfo/PDB/IPDBLineNumber.h | 36 + include/llvm/DebugInfo/PDB/IPDBRawSymbol.h | 211 + include/llvm/DebugInfo/PDB/IPDBSession.h | 56 + include/llvm/DebugInfo/PDB/IPDBSourceFile.h | 37 + include/llvm/DebugInfo/PDB/PDB.h | 23 + include/llvm/DebugInfo/PDB/PDBExtras.h | 37 + include/llvm/DebugInfo/PDB/PDBSymDumper.h | 85 + include/llvm/DebugInfo/PDB/PDBSymbol.h | 98 + include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolBlock.h | 41 + include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h | 38 + .../llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h | 55 + include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h | 37 + include/llvm/DebugInfo/PDB/PDBSymbolCustom.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolData.h | 61 + include/llvm/DebugInfo/PDB/PDBSymbolExe.h | 46 + include/llvm/DebugInfo/PDB/PDBSymbolFunc.h | 80 + include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h | 49 + .../llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h | 49 + include/llvm/DebugInfo/PDB/PDBSymbolLabel.h | 49 + include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h | 47 + include/llvm/DebugInfo/PDB/PDBSymbolThunk.h | 57 + include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h | 45 + .../llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h | 60 + include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h | 40 + include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h | 36 + .../llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h | 36 + include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h | 52 + include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h | 37 + .../llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h | 37 + .../llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h | 50 + include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h | 35 + include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h | 43 + include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h | 54 + include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h | 52 + include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h | 40 + .../llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h | 34 + .../llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h | 36 + include/llvm/DebugInfo/PDB/PDBTypes.h | 479 + include/llvm/ExecutionEngine/ExecutionEngine.h | 39 +- include/llvm/ExecutionEngine/JITEventListener.h | 19 +- include/llvm/ExecutionEngine/ObjectBuffer.h | 76 - include/llvm/ExecutionEngine/ObjectImage.h | 76 - include/llvm/ExecutionEngine/ObjectMemoryBuffer.h | 63 + include/llvm/ExecutionEngine/Orc/CloneSubModule.h | 60 + .../ExecutionEngine/Orc/CompileOnDemandLayer.h | 355 + include/llvm/ExecutionEngine/Orc/CompileUtils.h | 62 + include/llvm/ExecutionEngine/Orc/IRCompileLayer.h | 146 + .../llvm/ExecutionEngine/Orc/IndirectionUtils.h | 246 + include/llvm/ExecutionEngine/Orc/JITSymbol.h | 74 + .../llvm/ExecutionEngine/Orc/LazyEmittingLayer.h | 283 + .../llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h | 92 + .../llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h | 267 + .../llvm/ExecutionEngine/Orc/OrcTargetSupport.h | 56 + include/llvm/ExecutionEngine/OrcMCJITReplacement.h | 38 + include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 32 +- include/llvm/ExecutionEngine/RuntimeDyld.h | 55 +- include/llvm/ExecutionEngine/RuntimeDyldChecker.h | 1 + .../llvm/ExecutionEngine/SectionMemoryManager.h | 4 +- include/llvm/IR/Attributes.h | 5 + include/llvm/IR/BasicBlock.h | 12 +- include/llvm/IR/CFG.h | 26 +- include/llvm/IR/CallSite.h | 2 +- include/llvm/IR/Comdat.h | 2 +- include/llvm/IR/Constant.h | 4 +- include/llvm/IR/ConstantRange.h | 95 +- include/llvm/IR/Constants.h | 64 +- include/llvm/IR/DIBuilder.h | 118 +- include/llvm/IR/DataLayout.h | 7 + include/llvm/IR/DebugInfo.h | 293 +- include/llvm/IR/DebugInfoFlags.def | 36 + include/llvm/IR/DebugInfoMetadata.h | 1669 ++ include/llvm/IR/DebugLoc.h | 98 +- include/llvm/IR/DerivedTypes.h | 30 +- include/llvm/IR/DiagnosticInfo.h | 3 + include/llvm/IR/Dominators.h | 49 + include/llvm/IR/Function.h | 42 +- include/llvm/IR/GVMaterializer.h | 4 + include/llvm/IR/GlobalAlias.h | 4 +- include/llvm/IR/GlobalObject.h | 2 +- include/llvm/IR/GlobalValue.h | 3 +- include/llvm/IR/GlobalVariable.h | 6 +- include/llvm/IR/IRBuilder.h | 71 +- include/llvm/IR/IRPrintingPasses.h | 4 +- include/llvm/IR/InlineAsm.h | 4 +- include/llvm/IR/InstIterator.h | 12 + include/llvm/IR/InstrTypes.h | 32 +- include/llvm/IR/Instruction.h | 6 +- include/llvm/IR/Instructions.h | 37 +- include/llvm/IR/IntrinsicInst.h | 54 +- include/llvm/IR/Intrinsics.h | 30 +- include/llvm/IR/Intrinsics.td | 69 + include/llvm/IR/IntrinsicsBPF.td | 22 + include/llvm/IR/IntrinsicsHexagon.td | 319 +- include/llvm/IR/IntrinsicsPowerPC.td | 177 + include/llvm/IR/IntrinsicsR600.td | 3 + include/llvm/IR/IntrinsicsX86.td | 581 +- include/llvm/IR/LLVMContext.h | 4 +- include/llvm/IR/LeakDetector.h | 92 - include/llvm/IR/LegacyPassManager.h | 12 +- include/llvm/IR/LegacyPassManagers.h | 9 + include/llvm/IR/LegacyPassNameParser.h | 10 +- include/llvm/IR/MDBuilder.h | 8 + include/llvm/IR/Metadata.def | 99 + include/llvm/IR/Metadata.h | 947 +- include/llvm/IR/MetadataTracking.h | 99 + include/llvm/IR/Module.h | 55 +- include/llvm/IR/Operator.h | 22 +- include/llvm/IR/PassManager.h | 808 +- include/llvm/IR/PassManagerInternal.h | 349 + include/llvm/IR/PatternMatch.h | 751 +- include/llvm/IR/Statepoint.h | 298 + include/llvm/IR/TrackingMDRef.h | 170 + include/llvm/IR/Type.h | 3 + include/llvm/IR/TypeFinder.h | 1 + include/llvm/IR/Use.h | 2 +- include/llvm/IR/UseListOrder.h | 4 +- include/llvm/IR/User.h | 4 +- include/llvm/IR/Value.h | 64 +- include/llvm/IR/ValueHandle.h | 98 +- include/llvm/IR/ValueMap.h | 36 +- include/llvm/IR/Verifier.h | 4 +- include/llvm/InitializePasses.h | 32 +- include/llvm/LTO/LTOCodeGenerator.h | 22 +- include/llvm/LinkAllPasses.h | 9 +- include/llvm/Linker/Linker.h | 82 +- include/llvm/MC/MCAsmBackend.h | 18 +- include/llvm/MC/MCAsmInfo.h | 41 +- include/llvm/MC/MCAsmInfoDarwin.h | 2 +- include/llvm/MC/MCAssembler.h | 18 +- include/llvm/MC/MCCodeEmitter.h | 4 +- include/llvm/MC/MCContext.h | 16 +- include/llvm/MC/MCDwarf.h | 6 +- include/llvm/MC/MCELFObjectWriter.h | 1 + include/llvm/MC/MCExpr.h | 5 +- include/llvm/MC/MCInst.h | 22 +- include/llvm/MC/MCInstPrinter.h | 10 +- include/llvm/MC/MCInstrDesc.h | 11 +- include/llvm/MC/MCLabel.h | 4 +- include/llvm/MC/MCLinkerOptimizationHint.h | 2 +- include/llvm/MC/MCMachObjectWriter.h | 28 +- include/llvm/MC/MCObjectWriter.h | 10 +- include/llvm/MC/MCParser/AsmLexer.h | 4 +- include/llvm/MC/MCParser/MCAsmLexer.h | 4 +- include/llvm/MC/MCParser/MCAsmParser.h | 4 +- include/llvm/MC/MCParser/MCAsmParserExtension.h | 4 +- include/llvm/MC/MCRegisterInfo.h | 72 + include/llvm/MC/MCRelocationInfo.h | 4 +- include/llvm/MC/MCSection.h | 4 +- include/llvm/MC/MCSectionELF.h | 14 +- include/llvm/MC/MCStreamer.h | 14 +- include/llvm/MC/MCSubtargetInfo.h | 15 + include/llvm/MC/MCSymbol.h | 22 +- include/llvm/MC/MCSymbolizer.h | 4 +- include/llvm/MC/MCTargetAsmParser.h | 5 +- include/llvm/MC/MCTargetOptions.h | 12 +- include/llvm/MC/MCTargetOptionsCommandFlags.h | 8 +- include/llvm/MC/MCValue.h | 2 +- include/llvm/MC/MCWinCOFFObjectWriter.h | 15 +- include/llvm/MC/SectionKind.h | 6 +- include/llvm/Object/Archive.h | 22 +- include/llvm/Object/Binary.h | 4 +- include/llvm/Object/COFF.h | 14 +- include/llvm/Object/ELFObjectFile.h | 66 +- include/llvm/Object/ELFTypes.h | 52 +- include/llvm/Object/ELFYAML.h | 33 +- include/llvm/Object/IRObjectFile.h | 10 +- include/llvm/Object/MachO.h | 30 +- include/llvm/Object/MachOUniversal.h | 8 +- include/llvm/Object/ObjectFile.h | 27 +- include/llvm/Object/SymbolicFile.h | 5 +- include/llvm/Option/Arg.h | 4 +- include/llvm/Option/ArgList.h | 4 +- include/llvm/Option/OptSpecifier.h | 2 +- include/llvm/Pass.h | 4 +- include/llvm/PassAnalysisSupport.h | 2 +- include/llvm/PassInfo.h | 4 +- include/llvm/PassManager.h | 39 - include/llvm/ProfileData/CoverageMapping.h | 85 +- include/llvm/ProfileData/CoverageMappingReader.h | 81 +- include/llvm/ProfileData/CoverageMappingWriter.h | 2 +- include/llvm/ProfileData/InstrProfReader.h | 28 +- include/llvm/ProfileData/InstrProfWriter.h | 9 +- include/llvm/ProfileData/SampleProf.h | 1 - include/llvm/ProfileData/SampleProfReader.h | 6 +- include/llvm/Support/ARMBuildAttributes.h | 5 + include/llvm/Support/COFF.h | 12 +- include/llvm/Support/Casting.h | 34 + include/llvm/Support/CommandLine.h | 854 +- include/llvm/Support/Compiler.h | 91 +- include/llvm/Support/Compression.h | 2 +- include/llvm/Support/ConvertUTF.h | 8 + include/llvm/Support/CrashRecoveryContext.h | 3 +- include/llvm/Support/Dwarf.def | 351 + include/llvm/Support/Dwarf.h | 333 +- include/llvm/Support/ELF.h | 806 +- include/llvm/Support/ELFRelocs/AArch64.def | 147 + include/llvm/Support/ELFRelocs/ARM.def | 138 + include/llvm/Support/ELFRelocs/Hexagon.def | 92 + include/llvm/Support/ELFRelocs/Mips.def | 112 + include/llvm/Support/ELFRelocs/PowerPC.def | 61 + include/llvm/Support/ELFRelocs/PowerPC64.def | 88 + include/llvm/Support/ELFRelocs/Sparc.def | 89 + include/llvm/Support/ELFRelocs/SystemZ.def | 67 + include/llvm/Support/ELFRelocs/i386.def | 47 + include/llvm/Support/ELFRelocs/x86_64.def | 44 + include/llvm/Support/EndianStream.h | 25 + include/llvm/Support/ErrorOr.h | 2 +- include/llvm/Support/FileOutputBuffer.h | 6 +- include/llvm/Support/FileSystem.h | 48 +- include/llvm/Support/Format.h | 190 +- include/llvm/Support/GCOV.h | 147 +- include/llvm/Support/GenericDomTree.h | 322 +- include/llvm/Support/GenericDomTreeConstruction.h | 20 +- include/llvm/Support/LockFileManager.h | 8 +- include/llvm/Support/MachO.h | 351 +- include/llvm/Support/MathExtras.h | 332 +- include/llvm/Support/MemoryBuffer.h | 4 +- include/llvm/Support/Mutex.h | 4 +- include/llvm/Support/MutexGuard.h | 4 +- include/llvm/Support/OnDiskHashTable.h | 2 +- include/llvm/Support/PrettyStackTrace.h | 4 +- include/llvm/Support/Process.h | 102 +- include/llvm/Support/RWMutex.h | 4 +- include/llvm/Support/RandomNumberGenerator.h | 41 +- include/llvm/Support/Regex.h | 2 +- include/llvm/Support/Registry.h | 9 +- include/llvm/Support/ScaledNumber.h | 1 - include/llvm/Support/Signals.h | 3 + include/llvm/Support/SourceMgr.h | 4 +- include/llvm/Support/SpecialCaseList.h | 30 +- include/llvm/Support/StreamingMemoryObject.h | 13 +- include/llvm/Support/StringPool.h | 4 +- include/llvm/Support/SwapByteOrder.h | 20 + include/llvm/Support/TargetRegistry.h | 71 +- include/llvm/Support/ThreadLocal.h | 2 +- include/llvm/Support/Threading.h | 3 +- include/llvm/Support/Timer.h | 6 +- include/llvm/Support/UniqueLock.h | 4 +- include/llvm/Support/Watchdog.h | 4 +- include/llvm/Support/YAMLTraits.h | 17 +- include/llvm/Support/raw_ostream.h | 4 +- include/llvm/Support/type_traits.h | 10 +- include/llvm/TableGen/Record.h | 80 +- include/llvm/Target/Target.td | 55 +- include/llvm/Target/TargetCallingConv.h | 11 + include/llvm/Target/TargetFrameLowering.h | 19 + include/llvm/Target/TargetInstrInfo.h | 17 +- include/llvm/Target/TargetIntrinsicInfo.h | 4 +- include/llvm/Target/TargetLibraryInfo.h | 813 - include/llvm/Target/TargetLowering.h | 312 +- include/llvm/Target/TargetLoweringObjectFile.h | 33 +- include/llvm/Target/TargetMachine.h | 64 +- include/llvm/Target/TargetOpcodes.h | 13 +- include/llvm/Target/TargetOptions.h | 12 +- include/llvm/Target/TargetRegisterInfo.h | 32 +- include/llvm/Target/TargetSelectionDAG.td | 27 + include/llvm/Target/TargetSelectionDAGInfo.h | 5 +- include/llvm/Target/TargetSubtargetInfo.h | 10 +- include/llvm/Transforms/IPO.h | 4 + include/llvm/Transforms/IPO/LowerBitSets.h | 153 + include/llvm/Transforms/IPO/PassManagerBuilder.h | 21 +- include/llvm/Transforms/InstCombine/InstCombine.h | 46 + .../Transforms/InstCombine/InstCombineWorklist.h | 116 + include/llvm/Transforms/Instrumentation.h | 56 +- include/llvm/Transforms/Scalar.h | 37 +- include/llvm/Transforms/Scalar/EarlyCSE.h | 39 + .../llvm/Transforms/Scalar/LowerExpectIntrinsic.h | 40 + include/llvm/Transforms/Scalar/SimplifyCFG.h | 46 + include/llvm/Transforms/Utils/BasicBlockUtils.h | 158 +- include/llvm/Transforms/Utils/BuildLibCalls.h | 14 - include/llvm/Transforms/Utils/Cloning.h | 67 +- include/llvm/Transforms/Utils/Local.h | 23 +- include/llvm/Transforms/Utils/LoopUtils.h | 69 +- include/llvm/Transforms/Utils/PromoteMemToReg.h | 4 +- include/llvm/Transforms/Utils/SSAUpdater.h | 4 +- include/llvm/Transforms/Utils/SimplifyLibCalls.h | 70 +- include/llvm/Transforms/Utils/SymbolRewriter.h | 4 +- include/llvm/Transforms/Utils/UnrollLoop.h | 9 +- include/llvm/Transforms/Utils/ValueMapper.h | 21 +- include/llvm/Transforms/Utils/VectorUtils.h | 6 +- include/llvm/module.modulemap | 76 +- lib/Analysis/AliasAnalysis.cpp | 26 +- lib/Analysis/Analysis.cpp | 5 +- lib/Analysis/Android.mk | 6 +- lib/Analysis/AssumptionCache.cpp | 140 + lib/Analysis/AssumptionTracker.cpp | 110 - lib/Analysis/BasicAliasAnalysis.cpp | 191 +- lib/Analysis/BlockFrequencyInfo.cpp | 6 +- lib/Analysis/BlockFrequencyInfoImpl.cpp | 21 +- lib/Analysis/BranchProbabilityInfo.cpp | 9 +- lib/Analysis/CFG.cpp | 2 +- lib/Analysis/CFLAliasAnalysis.cpp | 61 +- lib/Analysis/CGSCCPassManager.cpp | 103 +- lib/Analysis/CMakeLists.txt | 9 +- lib/Analysis/CaptureTracking.cpp | 2 +- lib/Analysis/CodeMetrics.cpp | 26 +- lib/Analysis/ConstantFolding.cpp | 2 +- lib/Analysis/CostModel.cpp | 3 +- lib/Analysis/Delinearization.cpp | 6 +- lib/Analysis/DependenceAnalysis.cpp | 6 +- lib/Analysis/FunctionTargetTransformInfo.cpp | 50 - lib/Analysis/IPA/Android.mk | 1 - lib/Analysis/IPA/CMakeLists.txt | 1 - lib/Analysis/IPA/CallGraphSCCPass.cpp | 2 +- lib/Analysis/IPA/FindUsedTypes.cpp | 100 - lib/Analysis/IPA/IPA.cpp | 1 - lib/Analysis/IPA/InlineCost.cpp | 63 +- lib/Analysis/IVUsers.cpp | 6 +- lib/Analysis/InstructionSimplify.cpp | 700 +- lib/Analysis/LLVMBuild.txt | 2 +- lib/Analysis/LazyCallGraph.cpp | 5 +- lib/Analysis/LazyValueInfo.cpp | 341 +- lib/Analysis/LibCallSemantics.cpp | 39 + lib/Analysis/Lint.cpp | 232 +- lib/Analysis/Loads.cpp | 14 +- lib/Analysis/LoopAccessAnalysis.cpp | 1396 ++ lib/Analysis/LoopInfo.cpp | 92 +- lib/Analysis/LoopPass.cpp | 7 +- lib/Analysis/MemDepPrinter.cpp | 45 +- lib/Analysis/MemDerefPrinter.cpp | 70 + lib/Analysis/MemoryBuiltins.cpp | 4 +- lib/Analysis/MemoryDependenceAnalysis.cpp | 129 +- lib/Analysis/PHITransAddr.cpp | 6 +- lib/Analysis/RegionInfo.cpp | 2 +- lib/Analysis/RegionPass.cpp | 3 +- lib/Analysis/ScalarEvolution.cpp | 839 +- lib/Analysis/ScalarEvolutionExpander.cpp | 41 +- lib/Analysis/ScopedNoAliasAA.cpp | 2 +- lib/Analysis/TargetLibraryInfo.cpp | 810 + lib/Analysis/TargetTransformInfo.cpp | 629 +- lib/Analysis/TypeBasedAliasAnalysis.cpp | 27 +- lib/Analysis/ValueTracking.cpp | 389 +- lib/AsmParser/CMakeLists.txt | 3 + lib/AsmParser/LLLexer.cpp | 168 +- lib/AsmParser/LLLexer.h | 1 + lib/AsmParser/LLParser.cpp | 1236 +- lib/AsmParser/LLParser.h | 48 +- lib/AsmParser/LLToken.h | 14 +- lib/AsmParser/Parser.cpp | 2 +- lib/Bitcode/Reader/BitReader.cpp | 21 +- lib/Bitcode/Reader/BitcodeReader.cpp | 1363 +- lib/Bitcode/Reader/BitcodeReader.h | 58 +- lib/Bitcode/Reader/BitstreamReader.cpp | 8 +- lib/Bitcode/Reader/CMakeLists.txt | 3 + lib/Bitcode/Writer/BitcodeWriter.cpp | 658 +- lib/Bitcode/Writer/BitcodeWriterPass.cpp | 4 +- lib/Bitcode/Writer/ValueEnumerator.cpp | 215 +- lib/Bitcode/Writer/ValueEnumerator.h | 41 +- lib/CMakeLists.txt | 1 + lib/CodeGen/AggressiveAntiDepBreaker.cpp | 25 + lib/CodeGen/Analysis.cpp | 25 +- lib/CodeGen/Android.mk | 6 +- lib/CodeGen/AsmPrinter/ARMException.cpp | 3 +- lib/CodeGen/AsmPrinter/Android.mk | 1 + lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 519 +- lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 191 +- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 36 +- lib/CodeGen/AsmPrinter/ByteStreamer.h | 2 +- lib/CodeGen/AsmPrinter/CMakeLists.txt | 1 + lib/CodeGen/AsmPrinter/DIE.cpp | 3 +- lib/CodeGen/AsmPrinter/DIE.h | 587 - lib/CodeGen/AsmPrinter/DIEHash.cpp | 2 +- lib/CodeGen/AsmPrinter/DIEHash.h | 2 +- lib/CodeGen/AsmPrinter/DebugLocEntry.h | 14 +- lib/CodeGen/AsmPrinter/DebugLocList.h | 2 +- lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 2 +- lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 6 +- lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 5 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 114 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 4 +- lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 306 +- lib/CodeGen/AsmPrinter/DwarfDebug.h | 90 +- lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 269 + lib/CodeGen/AsmPrinter/DwarfExpression.h | 133 + lib/CodeGen/AsmPrinter/DwarfFile.cpp | 20 +- lib/CodeGen/AsmPrinter/DwarfFile.h | 12 +- lib/CodeGen/AsmPrinter/DwarfStringPool.h | 1 - lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 167 +- lib/CodeGen/AsmPrinter/DwarfUnit.h | 17 +- lib/CodeGen/AsmPrinter/EHStreamer.cpp | 59 +- lib/CodeGen/AsmPrinter/EHStreamer.h | 18 +- lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp | 45 +- lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 72 +- lib/CodeGen/AsmPrinter/Win64Exception.cpp | 146 +- lib/CodeGen/AsmPrinter/Win64Exception.h | 4 + lib/CodeGen/AtomicExpandPass.cpp | 50 +- lib/CodeGen/BasicTargetTransformInfo.cpp | 632 +- lib/CodeGen/BranchFolding.cpp | 3 +- lib/CodeGen/CMakeLists.txt | 8 + lib/CodeGen/CallingConvLower.cpp | 69 + lib/CodeGen/CodeGen.cpp | 1 - lib/CodeGen/CodeGenPrepare.cpp | 1139 +- lib/CodeGen/DeadMachineInstructionElim.cpp | 4 + lib/CodeGen/DwarfEHPrepare.cpp | 40 +- lib/CodeGen/EarlyIfConversion.cpp | 12 +- lib/CodeGen/ErlangGC.cpp | 50 +- lib/CodeGen/ExecutionDepsFix.cpp | 157 +- lib/CodeGen/ForwardControlFlowIntegrity.cpp | 4 +- lib/CodeGen/GCMetadata.cpp | 126 +- lib/CodeGen/GCMetadataPrinter.cpp | 12 +- lib/CodeGen/GCRootLowering.cpp | 351 + lib/CodeGen/GCStrategy.cpp | 415 +- lib/CodeGen/GlobalMerge.cpp | 39 +- lib/CodeGen/IfConversion.cpp | 12 +- lib/CodeGen/InlineSpiller.cpp | 25 +- lib/CodeGen/JumpInstrTables.cpp | 6 +- lib/CodeGen/LLVMTargetMachine.cpp | 34 +- lib/CodeGen/LexicalScopes.cpp | 26 +- lib/CodeGen/LiveDebugVariables.cpp | 1 - lib/CodeGen/LiveDebugVariables.h | 2 +- lib/CodeGen/LiveInterval.cpp | 776 +- lib/CodeGen/LiveIntervalAnalysis.cpp | 633 +- lib/CodeGen/LiveIntervalUnion.cpp | 18 +- lib/CodeGen/LiveRangeCalc.cpp | 262 +- lib/CodeGen/LiveRangeCalc.h | 78 +- lib/CodeGen/LiveRangeEdit.cpp | 29 +- lib/CodeGen/LiveRegMatrix.cpp | 62 +- lib/CodeGen/LocalStackSlotAllocation.cpp | 1 + lib/CodeGen/MachineBasicBlock.cpp | 13 +- lib/CodeGen/MachineBlockPlacement.cpp | 54 +- lib/CodeGen/MachineCSE.cpp | 42 +- lib/CodeGen/MachineCombiner.cpp | 28 +- lib/CodeGen/MachineDominanceFrontier.cpp | 2 +- lib/CodeGen/MachineFunction.cpp | 34 +- lib/CodeGen/MachineFunctionPass.cpp | 27 +- lib/CodeGen/MachineFunctionPrinterPass.cpp | 2 +- lib/CodeGen/MachineInstr.cpp | 103 +- lib/CodeGen/MachineLICM.cpp | 34 +- lib/CodeGen/MachineModuleInfo.cpp | 24 +- lib/CodeGen/MachineRegionInfo.cpp | 2 +- lib/CodeGen/MachineRegisterInfo.cpp | 16 +- lib/CodeGen/MachineScheduler.cpp | 23 +- lib/CodeGen/MachineSink.cpp | 34 +- lib/CodeGen/MachineTraceMetrics.cpp | 7 +- lib/CodeGen/MachineVerifier.cpp | 330 +- lib/CodeGen/OcamlGC.cpp | 13 +- lib/CodeGen/Passes.cpp | 152 +- lib/CodeGen/PeepholeOptimizer.cpp | 17 +- lib/CodeGen/PostRASchedulerList.cpp | 4 +- lib/CodeGen/PrologEpilogInserter.cpp | 68 +- lib/CodeGen/RegAllocBase.cpp | 2 + lib/CodeGen/RegAllocBase.h | 3 + lib/CodeGen/RegAllocFast.cpp | 21 +- lib/CodeGen/RegAllocGreedy.cpp | 209 +- lib/CodeGen/RegAllocPBQP.cpp | 172 +- lib/CodeGen/RegisterClassInfo.cpp | 2 + lib/CodeGen/RegisterCoalescer.cpp | 1301 +- lib/CodeGen/ScheduleDAG.cpp | 4 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 40 +- lib/CodeGen/SelectionDAG/Android.mk | 1 + lib/CodeGen/SelectionDAG/CMakeLists.txt | 1 + lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 1753 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 7 +- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 62 +- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 4 +- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 150 +- lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 2 +- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 89 +- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 11 + lib/CodeGen/SelectionDAG/LegalizeTypes.h | 7 + lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp | 38 +- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 197 + lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 28 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 224 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 435 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 36 +- lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 3 + lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 128 +- lib/CodeGen/SelectionDAG/StatepointLowering.cpp | 679 + lib/CodeGen/SelectionDAG/StatepointLowering.h | 138 + lib/CodeGen/SelectionDAG/TargetLowering.cpp | 92 +- lib/CodeGen/ShadowStackGC.cpp | 412 +- lib/CodeGen/ShadowStackGCLowering.cpp | 457 + lib/CodeGen/SjLjEHPrepare.cpp | 2 +- lib/CodeGen/SplitKit.cpp | 53 +- lib/CodeGen/StackColoring.cpp | 3 +- lib/CodeGen/StackMapLivenessAnalysis.cpp | 2 + lib/CodeGen/StackMaps.cpp | 17 +- lib/CodeGen/StackProtector.cpp | 66 +- lib/CodeGen/StatepointExampleGC.cpp | 55 + lib/CodeGen/TailDuplication.cpp | 3 +- lib/CodeGen/TargetFrameLoweringImpl.cpp | 5 + lib/CodeGen/TargetInstrInfo.cpp | 25 +- lib/CodeGen/TargetLoweringBase.cpp | 195 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 307 +- lib/CodeGen/TwoAddressInstructionPass.cpp | 6 +- lib/CodeGen/UnreachableBlockElim.cpp | 4 +- lib/CodeGen/VirtRegMap.cpp | 52 +- lib/CodeGen/WinEHPrepare.cpp | 626 + lib/DebugInfo/Android.mk | 53 - lib/DebugInfo/CMakeLists.txt | 22 +- lib/DebugInfo/DIContext.cpp | 18 - lib/DebugInfo/DWARF/Android.mk | 54 + lib/DebugInfo/DWARF/CMakeLists.txt | 22 + lib/DebugInfo/DWARF/DIContext.cpp | 18 + .../DWARF/DWARFAbbreviationDeclaration.cpp | 97 + lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 132 + lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 32 + lib/DebugInfo/DWARF/DWARFContext.cpp | 696 + lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp | 115 + lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp | 104 + lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 129 + lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 511 + lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 459 + lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 698 + lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 128 + lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 69 + lib/DebugInfo/DWARF/DWARFFormValue.cpp | 565 + lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 39 + lib/DebugInfo/DWARF/DWARFUnit.cpp | 377 + lib/DebugInfo/DWARF/LLVMBuild.txt | 22 + lib/DebugInfo/DWARF/Makefile | 14 + lib/DebugInfo/DWARF/SyntaxHighlighting.cpp | 37 + lib/DebugInfo/DWARF/SyntaxHighlighting.h | 39 + lib/DebugInfo/DWARF/module.modulemap | 1 + lib/DebugInfo/DWARFAbbreviationDeclaration.cpp | 97 - lib/DebugInfo/DWARFAbbreviationDeclaration.h | 60 - lib/DebugInfo/DWARFAcceleratorTable.cpp | 133 - lib/DebugInfo/DWARFAcceleratorTable.h | 51 - lib/DebugInfo/DWARFCompileUnit.cpp | 32 - lib/DebugInfo/DWARFCompileUnit.h | 31 - lib/DebugInfo/DWARFContext.cpp | 697 - lib/DebugInfo/DWARFContext.h | 292 - lib/DebugInfo/DWARFDebugAbbrev.cpp | 115 - lib/DebugInfo/DWARFDebugAbbrev.h | 63 - lib/DebugInfo/DWARFDebugArangeSet.cpp | 104 - lib/DebugInfo/DWARFDebugArangeSet.h | 70 - lib/DebugInfo/DWARFDebugAranges.cpp | 129 - lib/DebugInfo/DWARFDebugAranges.h | 87 - lib/DebugInfo/DWARFDebugFrame.cpp | 374 - lib/DebugInfo/DWARFDebugFrame.h | 43 - lib/DebugInfo/DWARFDebugInfoEntry.cpp | 451 - lib/DebugInfo/DWARFDebugInfoEntry.h | 160 - lib/DebugInfo/DWARFDebugLine.cpp | 698 - lib/DebugInfo/DWARFDebugLine.h | 238 - lib/DebugInfo/DWARFDebugLoc.cpp | 128 - lib/DebugInfo/DWARFDebugLoc.h | 81 - lib/DebugInfo/DWARFDebugRangeList.cpp | 69 - lib/DebugInfo/DWARFDebugRangeList.h | 77 - lib/DebugInfo/DWARFFormValue.cpp | 557 - lib/DebugInfo/DWARFRelocMap.h | 22 - lib/DebugInfo/DWARFSection.h | 24 - lib/DebugInfo/DWARFTypeUnit.cpp | 39 - lib/DebugInfo/DWARFTypeUnit.h | 38 - lib/DebugInfo/DWARFUnit.cpp | 377 - lib/DebugInfo/DWARFUnit.h | 245 - lib/DebugInfo/LLVMBuild.txt | 8 +- lib/DebugInfo/Makefile | 9 +- lib/DebugInfo/PDB/Android.mk | 75 + lib/DebugInfo/PDB/CMakeLists.txt | 76 + lib/DebugInfo/PDB/DIA/DIADataStream.cpp | 73 + lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp | 53 + lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp | 50 + lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp | 50 + lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp | 54 + lib/DebugInfo/PDB/DIA/DIALineNumber.cpp | 75 + lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 1095 + lib/DebugInfo/PDB/DIA/DIASession.cpp | 117 + lib/DebugInfo/PDB/DIA/DIASourceFile.cpp | 67 + lib/DebugInfo/PDB/IPDBSourceFile.cpp | 32 + lib/DebugInfo/PDB/LLVMBuild.txt | 23 + lib/DebugInfo/PDB/Makefile | 14 + lib/DebugInfo/PDB/PDB.cpp | 30 + lib/DebugInfo/PDB/PDBExtras.cpp | 346 + lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp | 28 + lib/DebugInfo/PDB/PDBSymDumper.cpp | 177 + lib/DebugInfo/PDB/PDBSymbol.cpp | 151 + lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolBlock.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolCompiland.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp | 32 + lib/DebugInfo/PDB/PDBSymbolCustom.cpp | 31 + lib/DebugInfo/PDB/PDBSymbolData.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolExe.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolFunc.cpp | 104 + lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolLabel.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolThunk.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp | 27 + lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp | 89 + lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolUnknown.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp | 26 + lib/DebugInfo/module.modulemap | 1 - lib/ExecutionEngine/Android.mk | 3 +- lib/ExecutionEngine/CMakeLists.txt | 8 +- lib/ExecutionEngine/EventListenerCommon.h | 9 +- lib/ExecutionEngine/ExecutionEngine.cpp | 48 +- lib/ExecutionEngine/ExecutionEngineBindings.cpp | 11 +- lib/ExecutionEngine/GDBRegistrationListener.cpp | 247 + .../IntelJITEvents/IntelJITEventListener.cpp | 67 +- lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt | 2 +- lib/ExecutionEngine/IntelJITEvents/jitprofiling.c | 5 +- lib/ExecutionEngine/JITEventListener.cpp | 15 - lib/ExecutionEngine/LLVMBuild.txt | 4 +- lib/ExecutionEngine/MCJIT/Android.mk | 5 +- lib/ExecutionEngine/MCJIT/CMakeLists.txt | 1 - lib/ExecutionEngine/MCJIT/MCJIT.cpp | 101 +- lib/ExecutionEngine/MCJIT/MCJIT.h | 22 +- lib/ExecutionEngine/MCJIT/ObjectBuffer.h | 48 + lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp | 178 - lib/ExecutionEngine/Makefile | 2 +- .../OProfileJIT/OProfileJITEventListener.cpp | 107 +- lib/ExecutionEngine/Orc/Android.mk | 18 + lib/ExecutionEngine/Orc/CMakeLists.txt | 9 + lib/ExecutionEngine/Orc/CloneSubModule.cpp | 108 + lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 118 + lib/ExecutionEngine/Orc/LLVMBuild.txt | 22 + lib/ExecutionEngine/Orc/Makefile | 13 + lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp | 128 + lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 332 + lib/ExecutionEngine/Orc/OrcTargetSupport.cpp | 128 + lib/ExecutionEngine/RTDyldMemoryManager.cpp | 282 - lib/ExecutionEngine/RuntimeDyld/Android.mk | 12 +- lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt | 2 +- lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp | 213 - lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h | 44 - .../RuntimeDyld/ObjectImageCommon.h | 86 - .../RuntimeDyld/RTDyldMemoryManager.cpp | 294 + lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 327 +- .../RuntimeDyld/RuntimeDyldChecker.cpp | 35 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 344 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 29 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 92 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 90 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 35 +- .../RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h | 19 +- .../RuntimeDyld/Targets/RuntimeDyldMachOARM.h | 56 +- .../RuntimeDyld/Targets/RuntimeDyldMachOI386.h | 78 +- .../RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h | 15 +- lib/ExecutionEngine/SectionMemoryManager.cpp | 178 + lib/Fuzzer/CMakeLists.txt | 21 + lib/Fuzzer/FuzzerCrossOver.cpp | 47 + lib/Fuzzer/FuzzerDriver.cpp | 199 + lib/Fuzzer/FuzzerFlags.def | 45 + lib/Fuzzer/FuzzerIO.cpp | 57 + lib/Fuzzer/FuzzerInterface.h | 25 + lib/Fuzzer/FuzzerInternal.h | 104 + lib/Fuzzer/FuzzerLoop.cpp | 233 + lib/Fuzzer/FuzzerMain.cpp | 20 + lib/Fuzzer/FuzzerMutate.cpp | 70 + lib/Fuzzer/FuzzerSanitizerOptions.cpp | 18 + lib/Fuzzer/FuzzerUtil.cpp | 61 + lib/Fuzzer/README.txt | 112 + lib/Fuzzer/test/CMakeLists.txt | 61 + lib/Fuzzer/test/FourIndependentBranchesTest.cpp | 18 + lib/Fuzzer/test/FullCoverageSetTest.cpp | 20 + lib/Fuzzer/test/FuzzerUnittest.cpp | 62 + lib/Fuzzer/test/InfiniteTest.cpp | 20 + lib/Fuzzer/test/NullDerefTest.cpp | 22 + lib/Fuzzer/test/SimpleTest.cpp | 21 + lib/Fuzzer/test/TimeoutTest.cpp | 22 + lib/Fuzzer/test/fuzzer.test | 19 + lib/Fuzzer/test/lit.cfg | 14 + lib/Fuzzer/test/lit.site.cfg.in | 3 + lib/Fuzzer/test/unit/lit.cfg | 7 + lib/Fuzzer/test/unit/lit.site.cfg.in | 2 + lib/IR/Android.mk | 4 +- lib/IR/AsmWriter.cpp | 835 +- lib/IR/AsmWriter.h | 4 +- lib/IR/AttributeImpl.h | 12 +- lib/IR/Attributes.cpp | 7 + lib/IR/AutoUpgrade.cpp | 272 +- lib/IR/BasicBlock.cpp | 24 +- lib/IR/CMakeLists.txt | 7 +- lib/IR/ConstantFold.cpp | 148 +- lib/IR/Constants.cpp | 146 +- lib/IR/ConstantsContext.h | 18 +- lib/IR/Core.cpp | 156 +- lib/IR/DIBuilder.cpp | 800 +- lib/IR/DataLayout.cpp | 62 +- lib/IR/DebugInfo.cpp | 284 +- lib/IR/DebugInfoMetadata.cpp | 418 + lib/IR/DebugLoc.cpp | 296 +- lib/IR/DiagnosticInfo.cpp | 3 +- lib/IR/Dominators.cpp | 38 +- lib/IR/Function.cpp | 124 +- lib/IR/GCOV.cpp | 332 +- lib/IR/Globals.cpp | 14 - lib/IR/IRBuilder.cpp | 119 +- lib/IR/IRPrintingPasses.cpp | 12 +- lib/IR/InlineAsm.cpp | 11 +- lib/IR/Instruction.cpp | 11 - lib/IR/Instructions.cpp | 48 +- lib/IR/IntrinsicInst.cpp | 22 +- lib/IR/LLVMContext.cpp | 22 +- lib/IR/LLVMContextImpl.cpp | 111 +- lib/IR/LLVMContextImpl.h | 864 +- lib/IR/LeakDetector.cpp | 69 - lib/IR/LeaksContext.h | 98 - lib/IR/LegacyPassManager.cpp | 55 +- lib/IR/MDBuilder.cpp | 47 +- lib/IR/Metadata.cpp | 1061 +- lib/IR/MetadataImpl.h | 46 + lib/IR/MetadataTracking.cpp | 55 + lib/IR/Module.cpp | 80 +- lib/IR/Pass.cpp | 4 +- lib/IR/PassManager.cpp | 165 +- lib/IR/Statepoint.cpp | 77 + lib/IR/Type.cpp | 21 +- lib/IR/TypeFinder.cpp | 30 +- lib/IR/Value.cpp | 129 +- lib/IR/ValueSymbolTable.cpp | 10 +- lib/IR/Verifier.cpp | 658 +- lib/IRReader/CMakeLists.txt | 3 + lib/LTO/CMakeLists.txt | 5 + lib/LTO/LLVMBuild.txt | 2 +- lib/LTO/LTOCodeGenerator.cpp | 172 +- lib/LTO/LTOModule.cpp | 66 +- lib/LineEditor/CMakeLists.txt | 5 +- lib/Linker/CMakeLists.txt | 3 + lib/Linker/LinkModules.cpp | 1271 +- lib/MC/CMakeLists.txt | 3 + lib/MC/ConstantPools.cpp | 2 +- lib/MC/ELFObjectWriter.cpp | 259 +- lib/MC/MCAsmInfo.cpp | 6 + lib/MC/MCAsmInfoDarwin.cpp | 38 +- lib/MC/MCAsmInfoELF.cpp | 4 +- lib/MC/MCAsmStreamer.cpp | 25 +- lib/MC/MCAssembler.cpp | 35 +- lib/MC/MCContext.cpp | 48 +- lib/MC/MCDisassembler/Disassembler.cpp | 10 +- lib/MC/MCDisassembler/MCExternalSymbolizer.cpp | 10 +- lib/MC/MCDwarf.cpp | 24 +- lib/MC/MCELF.cpp | 4 +- lib/MC/MCELFStreamer.cpp | 18 +- lib/MC/MCExpr.cpp | 84 +- lib/MC/MCInst.cpp | 15 +- lib/MC/MCInstPrinter.cpp | 6 +- lib/MC/MCLinkerOptimizationHint.cpp | 2 +- lib/MC/MCMachOStreamer.cpp | 2 +- lib/MC/MCObjectFileInfo.cpp | 320 +- lib/MC/MCObjectStreamer.cpp | 4 +- lib/MC/MCParser/AsmParser.cpp | 49 +- lib/MC/MCParser/CMakeLists.txt | 3 + lib/MC/MCParser/COFFAsmParser.cpp | 8 +- lib/MC/MCParser/ELFAsmParser.cpp | 54 +- lib/MC/MCSectionCOFF.cpp | 8 +- lib/MC/MCSectionELF.cpp | 17 +- lib/MC/MCSubtargetInfo.cpp | 3 +- lib/MC/MCTargetOptions.cpp | 7 +- lib/MC/MCValue.cpp | 4 +- lib/MC/MCWinEH.cpp | 59 +- lib/MC/MachObjectWriter.cpp | 47 +- lib/MC/WinCOFFObjectWriter.cpp | 70 +- lib/MC/WinCOFFStreamer.cpp | 2 +- lib/Makefile | 4 +- lib/Object/Archive.cpp | 72 +- lib/Object/Binary.cpp | 1 + lib/Object/CMakeLists.txt | 3 + lib/Object/COFFObjectFile.cpp | 33 +- lib/Object/ELF.cpp | 756 +- lib/Object/ELFYAML.cpp | 409 +- lib/Object/IRObjectFile.cpp | 22 +- lib/Object/MachOObjectFile.cpp | 175 +- lib/Object/MachOUniversal.cpp | 26 +- lib/Object/ObjectFile.cpp | 1 + lib/Object/SymbolicFile.cpp | 5 +- lib/Option/Arg.cpp | 12 +- lib/Option/ArgList.cpp | 6 +- lib/Option/CMakeLists.txt | 3 + lib/ProfileData/CMakeLists.txt | 3 + lib/ProfileData/CoverageMapping.cpp | 110 +- lib/ProfileData/CoverageMappingReader.cpp | 161 +- lib/ProfileData/CoverageMappingWriter.cpp | 8 +- lib/ProfileData/InstrProfIndexed.h | 1 + lib/ProfileData/InstrProfReader.cpp | 42 +- lib/ProfileData/InstrProfWriter.cpp | 34 +- lib/ProfileData/SampleProfWriter.cpp | 2 +- lib/Support/APFloat.cpp | 2 +- lib/Support/APInt.cpp | 22 +- lib/Support/CMakeLists.txt | 28 +- lib/Support/CommandLine.cpp | 868 +- lib/Support/Compression.cpp | 6 + lib/Support/ConvertUTFWrapper.cpp | 45 +- lib/Support/Debug.cpp | 66 +- lib/Support/Dwarf.cpp | 360 +- lib/Support/Errno.cpp | 8 +- lib/Support/ErrorHandling.cpp | 2 +- lib/Support/FileOutputBuffer.cpp | 27 +- lib/Support/Host.cpp | 99 +- lib/Support/LockFileManager.cpp | 54 +- lib/Support/MemoryBuffer.cpp | 6 +- lib/Support/Path.cpp | 13 +- lib/Support/PrettyStackTrace.cpp | 50 +- lib/Support/Process.cpp | 25 - lib/Support/RandomNumberGenerator.cpp | 30 +- lib/Support/ScaledNumber.cpp | 2 +- lib/Support/SmallPtrSet.cpp | 19 +- lib/Support/SpecialCaseList.cpp | 58 +- lib/Support/StreamingMemoryObject.cpp | 4 +- lib/Support/StringMap.cpp | 5 +- lib/Support/ThreadLocal.cpp | 47 +- lib/Support/Triple.cpp | 58 +- lib/Support/Unix/Host.inc | 30 +- lib/Support/Unix/Memory.inc | 19 +- lib/Support/Unix/Path.inc | 113 +- lib/Support/Unix/Process.inc | 50 +- lib/Support/Unix/Program.inc | 26 +- lib/Support/Unix/Signals.inc | 2 + lib/Support/Unix/ThreadLocal.inc | 45 +- lib/Support/Valgrind.cpp | 3 +- lib/Support/Windows/Path.inc | 159 +- lib/Support/Windows/Process.inc | 31 +- lib/Support/Windows/Program.inc | 20 +- lib/Support/Windows/Signals.inc | 51 +- lib/Support/Windows/ThreadLocal.inc | 2 +- lib/Support/Windows/WindowsSupport.h | 13 +- lib/Support/Windows/explicit_symbols.inc | 6 + lib/Support/YAMLParser.cpp | 10 +- lib/Support/YAMLTraits.cpp | 18 +- lib/Support/raw_ostream.cpp | 10 +- lib/Support/regcomp.c | 21 + lib/TableGen/CMakeLists.txt | 3 + lib/TableGen/Main.cpp | 7 +- lib/TableGen/Record.cpp | 4 +- lib/TableGen/TGParser.cpp | 180 +- lib/TableGen/TGParser.h | 2 +- lib/Target/AArch64/AArch64.h | 3 - lib/Target/AArch64/AArch64.td | 2 + lib/Target/AArch64/AArch64A53Fix835769.cpp | 13 +- lib/Target/AArch64/AArch64A57FPLoadBalancing.cpp | 40 +- lib/Target/AArch64/AArch64AdvSIMDScalarPass.cpp | 8 +- lib/Target/AArch64/AArch64AsmPrinter.cpp | 40 +- lib/Target/AArch64/AArch64BranchRelaxation.cpp | 4 +- lib/Target/AArch64/AArch64CallingConvention.h | 141 + lib/Target/AArch64/AArch64CallingConvention.td | 47 +- .../AArch64/AArch64CleanupLocalDynamicTLSPass.cpp | 8 +- lib/Target/AArch64/AArch64CollectLOH.cpp | 10 +- lib/Target/AArch64/AArch64ConditionOptimizer.cpp | 2 +- lib/Target/AArch64/AArch64ConditionalCompares.cpp | 6 +- lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp | 4 +- lib/Target/AArch64/AArch64FastISel.cpp | 70 +- lib/Target/AArch64/AArch64FrameLowering.cpp | 35 +- lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 176 +- lib/Target/AArch64/AArch64ISelLowering.cpp | 292 +- lib/Target/AArch64/AArch64ISelLowering.h | 20 +- lib/Target/AArch64/AArch64InstrFormats.td | 2 +- lib/Target/AArch64/AArch64InstrInfo.cpp | 7 +- lib/Target/AArch64/AArch64InstrInfo.h | 2 +- lib/Target/AArch64/AArch64InstrInfo.td | 87 +- lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp | 22 +- lib/Target/AArch64/AArch64PBQPRegAlloc.cpp | 6 +- lib/Target/AArch64/AArch64PromoteConstant.cpp | 152 +- lib/Target/AArch64/AArch64RegisterInfo.cpp | 20 +- lib/Target/AArch64/AArch64SelectionDAGInfo.cpp | 9 +- lib/Target/AArch64/AArch64StorePairSuppress.cpp | 19 +- lib/Target/AArch64/AArch64Subtarget.cpp | 15 +- lib/Target/AArch64/AArch64Subtarget.h | 6 +- lib/Target/AArch64/AArch64TargetMachine.cpp | 56 +- lib/Target/AArch64/AArch64TargetMachine.h | 6 +- lib/Target/AArch64/AArch64TargetTransformInfo.cpp | 315 +- lib/Target/AArch64/AArch64TargetTransformInfo.h | 147 + lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 80 +- .../AArch64/Disassembler/AArch64Disassembler.cpp | 12 +- .../AArch64/MCTargetDesc/AArch64AddressingModes.h | 13 +- .../AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 42 +- .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 2 +- .../AArch64/MCTargetDesc/AArch64ELFStreamer.cpp | 4 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 2 + lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h | 3 +- .../AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp | 3 +- .../MCTargetDesc/AArch64MachObjectWriter.cpp | 89 +- lib/Target/ARM/ARM.h | 4 - lib/Target/ARM/ARM.td | 36 +- lib/Target/ARM/ARMArchExtName.def | 30 + lib/Target/ARM/ARMArchExtName.h | 26 + lib/Target/ARM/ARMAsmPrinter.cpp | 278 +- lib/Target/ARM/ARMAsmPrinter.h | 22 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 51 +- lib/Target/ARM/ARMBaseInstrInfo.h | 4 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 38 +- lib/Target/ARM/ARMBaseRegisterInfo.h | 2 +- lib/Target/ARM/ARMCallingConv.h | 161 +- lib/Target/ARM/ARMCallingConv.td | 2 +- lib/Target/ARM/ARMConstantIslandPass.cpp | 14 +- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 18 +- lib/Target/ARM/ARMFastISel.cpp | 57 +- lib/Target/ARM/ARMFrameLowering.cpp | 255 +- lib/Target/ARM/ARMFrameLowering.h | 2 + lib/Target/ARM/ARMHazardRecognizer.cpp | 5 +- lib/Target/ARM/ARMISelDAGToDAG.cpp | 37 +- lib/Target/ARM/ARMISelLowering.cpp | 711 +- lib/Target/ARM/ARMISelLowering.h | 19 +- lib/Target/ARM/ARMInstrInfo.cpp | 26 +- lib/Target/ARM/ARMInstrInfo.td | 265 +- lib/Target/ARM/ARMInstrNEON.td | 20 +- lib/Target/ARM/ARMInstrThumb.td | 25 +- lib/Target/ARM/ARMInstrThumb2.td | 106 +- lib/Target/ARM/ARMInstrVFP.td | 18 +- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 68 +- lib/Target/ARM/ARMMCInstLower.cpp | 36 +- lib/Target/ARM/ARMMachineFunctionInfo.cpp | 4 +- lib/Target/ARM/ARMMachineFunctionInfo.h | 2 +- lib/Target/ARM/ARMOptimizeBarriersPass.cpp | 2 +- lib/Target/ARM/ARMRegisterInfo.td | 10 +- lib/Target/ARM/ARMSelectionDAGInfo.cpp | 9 +- lib/Target/ARM/ARMSubtarget.cpp | 122 +- lib/Target/ARM/ARMSubtarget.h | 36 +- lib/Target/ARM/ARMTargetMachine.cpp | 155 +- lib/Target/ARM/ARMTargetMachine.h | 14 +- lib/Target/ARM/ARMTargetObjectFile.cpp | 10 +- lib/Target/ARM/ARMTargetTransformInfo.cpp | 215 +- lib/Target/ARM/ARMTargetTransformInfo.h | 134 + lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 510 +- lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 37 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 65 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 1 + lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 21 +- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 61 +- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 4 +- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h | 3 +- lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 26 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 72 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 3 +- .../ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 37 +- lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp | 1 + .../ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp | 14 +- lib/Target/ARM/MLxExpansionPass.cpp | 2 +- lib/Target/ARM/Thumb1FrameLowering.cpp | 54 +- lib/Target/ARM/Thumb1InstrInfo.cpp | 2 +- lib/Target/ARM/Thumb1RegisterInfo.cpp | 23 +- lib/Target/ARM/Thumb2ITBlockPass.cpp | 10 +- lib/Target/ARM/Thumb2InstrInfo.cpp | 9 +- lib/Target/ARM/Thumb2SizeReduction.cpp | 13 +- lib/Target/Android.mk | 3 +- lib/Target/BPF/BPF.h | 22 + lib/Target/BPF/BPF.td | 31 + lib/Target/BPF/BPFAsmPrinter.cpp | 87 + lib/Target/BPF/BPFCallingConv.td | 29 + lib/Target/BPF/BPFFrameLowering.cpp | 39 + lib/Target/BPF/BPFFrameLowering.h | 41 + lib/Target/BPF/BPFISelDAGToDAG.cpp | 159 + lib/Target/BPF/BPFISelLowering.cpp | 642 + lib/Target/BPF/BPFISelLowering.h | 89 + lib/Target/BPF/BPFInstrFormats.td | 33 + lib/Target/BPF/BPFInstrInfo.cpp | 168 + lib/Target/BPF/BPFInstrInfo.h | 60 + lib/Target/BPF/BPFInstrInfo.td | 507 + lib/Target/BPF/BPFMCInstLower.cpp | 77 + lib/Target/BPF/BPFMCInstLower.h | 43 + lib/Target/BPF/BPFRegisterInfo.cpp | 88 + lib/Target/BPF/BPFRegisterInfo.h | 41 + lib/Target/BPF/BPFRegisterInfo.td | 41 + lib/Target/BPF/BPFSubtarget.cpp | 31 + lib/Target/BPF/BPFSubtarget.h | 64 + lib/Target/BPF/BPFTargetMachine.cpp | 69 + lib/Target/BPF/BPFTargetMachine.h | 42 + lib/Target/BPF/CMakeLists.txt | 27 + lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp | 86 + lib/Target/BPF/InstPrinter/BPFInstPrinter.h | 41 + lib/Target/BPF/InstPrinter/CMakeLists.txt | 3 + lib/Target/BPF/InstPrinter/LLVMBuild.txt | 23 + lib/Target/BPF/InstPrinter/Makefile | 16 + lib/Target/BPF/LLVMBuild.txt | 32 + lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 83 + lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp | 53 + lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h | 36 + lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp | 167 + lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp | 111 + lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h | 59 + lib/Target/BPF/MCTargetDesc/CMakeLists.txt | 6 + lib/Target/BPF/MCTargetDesc/LLVMBuild.txt | 23 + lib/Target/BPF/MCTargetDesc/Makefile | 16 + lib/Target/BPF/Makefile | 21 + lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp | 18 + lib/Target/BPF/TargetInfo/CMakeLists.txt | 3 + lib/Target/BPF/TargetInfo/LLVMBuild.txt | 23 + lib/Target/BPF/TargetInfo/Makefile | 16 + lib/Target/CMakeLists.txt | 8 +- lib/Target/CppBackend/CPPBackend.cpp | 4 +- lib/Target/Hexagon/CMakeLists.txt | 1 - .../Hexagon/Disassembler/HexagonDisassembler.cpp | 105 +- lib/Target/Hexagon/Disassembler/LLVMBuild.txt | 2 +- lib/Target/Hexagon/Hexagon.h | 20 +- lib/Target/Hexagon/Hexagon.td | 48 +- lib/Target/Hexagon/HexagonAsmPrinter.cpp | 36 +- lib/Target/Hexagon/HexagonAsmPrinter.h | 9 +- lib/Target/Hexagon/HexagonCFGOptimizer.cpp | 42 +- lib/Target/Hexagon/HexagonCallingConvLower.cpp | 206 - lib/Target/Hexagon/HexagonCallingConvLower.h | 187 - lib/Target/Hexagon/HexagonCopyToCombine.cpp | 50 +- lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp | 62 +- lib/Target/Hexagon/HexagonFixupHwLoops.cpp | 12 +- lib/Target/Hexagon/HexagonFrameLowering.cpp | 25 +- lib/Target/Hexagon/HexagonHardwareLoops.cpp | 72 +- lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 393 +- lib/Target/Hexagon/HexagonISelLowering.cpp | 116 +- lib/Target/Hexagon/HexagonISelLowering.h | 28 +- lib/Target/Hexagon/HexagonInstrFormats.td | 35 +- lib/Target/Hexagon/HexagonInstrFormatsV4.td | 5 + lib/Target/Hexagon/HexagonInstrInfo.cpp | 729 +- lib/Target/Hexagon/HexagonInstrInfo.td | 7056 ++++-- lib/Target/Hexagon/HexagonInstrInfoV3.td | 249 +- lib/Target/Hexagon/HexagonInstrInfoV4.td | 5452 ++-- lib/Target/Hexagon/HexagonInstrInfoV5.td | 1424 +- lib/Target/Hexagon/HexagonInstrInfoVector.td | 65 + lib/Target/Hexagon/HexagonIntrinsics.td | 4509 +--- lib/Target/Hexagon/HexagonIntrinsicsDerived.td | 11 +- lib/Target/Hexagon/HexagonIntrinsicsV3.td | 51 +- lib/Target/Hexagon/HexagonIntrinsicsV4.td | 578 +- lib/Target/Hexagon/HexagonIntrinsicsV5.td | 506 +- lib/Target/Hexagon/HexagonMCInstLower.cpp | 4 +- lib/Target/Hexagon/HexagonMachineScheduler.cpp | 15 +- lib/Target/Hexagon/HexagonMachineScheduler.h | 8 +- lib/Target/Hexagon/HexagonNewValueJump.cpp | 95 +- lib/Target/Hexagon/HexagonOperands.td | 344 +- lib/Target/Hexagon/HexagonPeephole.cpp | 23 +- lib/Target/Hexagon/HexagonRegisterInfo.cpp | 90 +- lib/Target/Hexagon/HexagonRegisterInfo.td | 131 +- lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp | 3 +- .../Hexagon/HexagonSplitConst32AndConst64.cpp | 24 +- lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp | 115 +- lib/Target/Hexagon/HexagonSubtarget.cpp | 12 +- lib/Target/Hexagon/HexagonSubtarget.h | 23 +- lib/Target/Hexagon/HexagonTargetMachine.cpp | 50 +- lib/Target/Hexagon/HexagonTargetMachine.h | 3 +- lib/Target/Hexagon/HexagonTargetObjectFile.cpp | 15 +- lib/Target/Hexagon/HexagonVLIWPacketizer.cpp | 173 +- .../Hexagon/HexagonVarargsCallingConvention.h | 149 - lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt | 2 +- lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h | 1 - .../Hexagon/MCTargetDesc/HexagonInstPrinter.cpp | 25 +- .../Hexagon/MCTargetDesc/HexagonInstPrinter.h | 11 +- .../Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp | 15 +- .../Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h | 5 +- lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp | 176 - lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h | 100 - .../Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp | 223 + .../Hexagon/MCTargetDesc/HexagonMCInstrInfo.h | 106 + .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp | 2 +- .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.h | 2 + lib/Target/LLVMBuild.txt | 4 +- lib/Target/MSP430/MSP430AsmPrinter.cpp | 4 +- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 7 +- lib/Target/MSP430/MSP430ISelLowering.cpp | 47 +- lib/Target/MSP430/MSP430ISelLowering.h | 9 +- lib/Target/MSP430/MSP430InstrInfo.td | 6 +- lib/Target/MSP430/MSP430MCInstLower.cpp | 5 +- lib/Target/MSP430/MSP430Subtarget.cpp | 8 +- lib/Target/MSP430/MSP430Subtarget.h | 4 +- lib/Target/MSP430/MSP430TargetMachine.cpp | 14 +- lib/Target/MSP430/MSP430TargetMachine.h | 2 + lib/Target/MSP430/README.txt | 1 + lib/Target/Mips/Android.mk | 1 - lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 723 +- lib/Target/Mips/CMakeLists.txt | 1 - lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 618 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp | 12 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.h | 1 + lib/Target/Mips/MCTargetDesc/Android.mk | 1 + lib/Target/Mips/MCTargetDesc/CMakeLists.txt | 1 + lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h | 8 + lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 92 + lib/Target/Mips/MCTargetDesc/MipsABIInfo.h | 67 + lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 24 +- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h | 2 +- .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 14 +- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h | 2 +- lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h | 6 + lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 1 + lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 204 +- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h | 52 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 23 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h | 11 +- lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp | 19 +- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 117 +- lib/Target/Mips/MicroMipsInstrFormats.td | 126 + lib/Target/Mips/MicroMipsInstrInfo.td | 349 +- lib/Target/Mips/Mips.h | 1 - lib/Target/Mips/Mips.td | 56 +- lib/Target/Mips/Mips16FrameLowering.cpp | 8 +- lib/Target/Mips/Mips16HardFloat.cpp | 26 +- lib/Target/Mips/Mips16HardFloat.h | 16 +- lib/Target/Mips/Mips16ISelDAGToDAG.cpp | 13 +- lib/Target/Mips/Mips16ISelLowering.cpp | 65 +- lib/Target/Mips/Mips16InstrInfo.cpp | 6 +- lib/Target/Mips/Mips16InstrInfo.td | 16 +- lib/Target/Mips/Mips16RegisterInfo.cpp | 7 +- lib/Target/Mips/Mips32r6InstrInfo.td | 8 +- lib/Target/Mips/Mips64InstrInfo.td | 124 +- lib/Target/Mips/MipsABIInfo.cpp | 45 - lib/Target/Mips/MipsABIInfo.h | 61 - lib/Target/Mips/MipsAsmPrinter.cpp | 183 +- lib/Target/Mips/MipsAsmPrinter.h | 41 +- lib/Target/Mips/MipsCCState.cpp | 4 +- lib/Target/Mips/MipsCCState.h | 6 +- lib/Target/Mips/MipsCallingConv.td | 45 +- lib/Target/Mips/MipsCondMov.td | 37 + lib/Target/Mips/MipsConstantIslandPass.cpp | 8 +- lib/Target/Mips/MipsDelaySlotFiller.cpp | 188 +- lib/Target/Mips/MipsFastISel.cpp | 282 +- lib/Target/Mips/MipsFrameLowering.cpp | 2 +- lib/Target/Mips/MipsISelDAGToDAG.cpp | 17 +- lib/Target/Mips/MipsISelDAGToDAG.h | 8 +- lib/Target/Mips/MipsISelLowering.cpp | 447 +- lib/Target/Mips/MipsISelLowering.h | 47 +- lib/Target/Mips/MipsInstrFPU.td | 28 +- lib/Target/Mips/MipsInstrFormats.td | 27 + lib/Target/Mips/MipsInstrInfo.cpp | 2 +- lib/Target/Mips/MipsInstrInfo.td | 84 +- lib/Target/Mips/MipsLongBranch.cpp | 55 +- lib/Target/Mips/MipsMachineFunction.cpp | 30 +- lib/Target/Mips/MipsOptimizePICCall.cpp | 2 +- lib/Target/Mips/MipsOptionRecord.h | 6 +- lib/Target/Mips/MipsRegisterInfo.cpp | 10 +- lib/Target/Mips/MipsRegisterInfo.td | 42 +- lib/Target/Mips/MipsSEFrameLowering.cpp | 80 +- lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 67 +- lib/Target/Mips/MipsSEISelDAGToDAG.h | 3 + lib/Target/Mips/MipsSEISelLowering.cpp | 90 +- lib/Target/Mips/MipsSEInstrInfo.cpp | 27 +- lib/Target/Mips/MipsSEInstrInfo.h | 1 - lib/Target/Mips/MipsSubtarget.cpp | 147 +- lib/Target/Mips/MipsSubtarget.h | 59 +- lib/Target/Mips/MipsTargetMachine.cpp | 99 +- lib/Target/Mips/MipsTargetMachine.h | 11 +- lib/Target/Mips/MipsTargetObjectFile.cpp | 24 +- lib/Target/Mips/MipsTargetStreamer.h | 24 +- lib/Target/NVPTX/LLVMBuild.txt | 2 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 1 + lib/Target/NVPTX/NVPTX.h | 5 +- lib/Target/NVPTX/NVPTXAllocaHoisting.h | 3 +- lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 350 +- lib/Target/NVPTX/NVPTXAsmPrinter.h | 39 +- lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp | 2 +- lib/Target/NVPTX/NVPTXFrameLowering.cpp | 7 +- lib/Target/NVPTX/NVPTXFrameLowering.h | 10 +- lib/Target/NVPTX/NVPTXGenericToNVVM.cpp | 61 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 124 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.h | 5 +- lib/Target/NVPTX/NVPTXISelLowering.cpp | 134 +- lib/Target/NVPTX/NVPTXISelLowering.h | 12 +- lib/Target/NVPTX/NVPTXImageOptimizer.cpp | 2 +- lib/Target/NVPTX/NVPTXInstrInfo.cpp | 6 +- lib/Target/NVPTX/NVPTXInstrInfo.h | 2 +- lib/Target/NVPTX/NVPTXInstrInfo.td | 72 +- lib/Target/NVPTX/NVPTXLowerAggrCopies.h | 3 +- lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp | 6 +- lib/Target/NVPTX/NVPTXRegisterInfo.cpp | 3 +- lib/Target/NVPTX/NVPTXRegisterInfo.h | 8 +- lib/Target/NVPTX/NVPTXReplaceImageHandles.cpp | 8 +- lib/Target/NVPTX/NVPTXSubtarget.cpp | 40 +- lib/Target/NVPTX/NVPTXSubtarget.h | 20 +- lib/Target/NVPTX/NVPTXTargetMachine.cpp | 41 +- lib/Target/NVPTX/NVPTXTargetMachine.h | 13 +- lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp | 88 +- lib/Target/NVPTX/NVPTXTargetTransformInfo.h | 74 + lib/Target/NVPTX/NVPTXUtilities.cpp | 13 +- lib/Target/NVPTX/NVPTXVector.td | 4 +- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 53 +- lib/Target/PowerPC/CMakeLists.txt | 6 + .../PowerPC/Disassembler/PPCDisassembler.cpp | 29 + lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp | 23 +- lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h | 1 + lib/Target/PowerPC/LLVMBuild.txt | 2 +- lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 2 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 5 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h | 3 +- .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 4 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 17 + .../PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp | 16 +- lib/Target/PowerPC/PPC.h | 14 +- lib/Target/PowerPC/PPC.td | 104 +- lib/Target/PowerPC/PPCAsmPrinter.cpp | 343 +- lib/Target/PowerPC/PPCBranchSelector.cpp | 25 + lib/Target/PowerPC/PPCCTRLoops.cpp | 37 +- lib/Target/PowerPC/PPCCallingConv.h | 35 + lib/Target/PowerPC/PPCCallingConv.td | 83 +- lib/Target/PowerPC/PPCEarlyReturn.cpp | 201 + lib/Target/PowerPC/PPCFastISel.cpp | 203 +- lib/Target/PowerPC/PPCFrameLowering.cpp | 252 +- lib/Target/PowerPC/PPCFrameLowering.h | 48 +- lib/Target/PowerPC/PPCHazardRecognizers.cpp | 4 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 2314 +- lib/Target/PowerPC/PPCISelLowering.cpp | 2863 ++- lib/Target/PowerPC/PPCISelLowering.h | 211 +- lib/Target/PowerPC/PPCInstr64Bit.td | 142 +- lib/Target/PowerPC/PPCInstrAltivec.td | 64 + lib/Target/PowerPC/PPCInstrFormats.td | 175 + lib/Target/PowerPC/PPCInstrInfo.cpp | 746 +- lib/Target/PowerPC/PPCInstrInfo.h | 9 + lib/Target/PowerPC/PPCInstrInfo.td | 247 +- lib/Target/PowerPC/PPCInstrQPX.td | 1192 + lib/Target/PowerPC/PPCInstrVSX.td | 81 +- lib/Target/PowerPC/PPCLoopDataPrefetch.cpp | 231 + lib/Target/PowerPC/PPCLoopPreIncPrep.cpp | 382 + lib/Target/PowerPC/PPCMCInstLower.cpp | 10 +- lib/Target/PowerPC/PPCMachineFunctionInfo.cpp | 7 +- lib/Target/PowerPC/PPCMachineFunctionInfo.h | 14 + lib/Target/PowerPC/PPCRegisterInfo.cpp | 123 +- lib/Target/PowerPC/PPCRegisterInfo.h | 2 + lib/Target/PowerPC/PPCRegisterInfo.td | 86 +- lib/Target/PowerPC/PPCSchedule.td | 3 + lib/Target/PowerPC/PPCSchedule440.td | 8 + lib/Target/PowerPC/PPCScheduleA2.td | 2 + lib/Target/PowerPC/PPCScheduleE500mc.td | 6 + lib/Target/PowerPC/PPCScheduleE5500.td | 6 + lib/Target/PowerPC/PPCScheduleP7.td | 7 + lib/Target/PowerPC/PPCScheduleP8.td | 401 + lib/Target/PowerPC/PPCSubtarget.cpp | 92 +- lib/Target/PowerPC/PPCSubtarget.h | 48 +- lib/Target/PowerPC/PPCTLSDynamicCall.cpp | 168 + lib/Target/PowerPC/PPCTargetMachine.cpp | 161 +- lib/Target/PowerPC/PPCTargetMachine.h | 23 +- lib/Target/PowerPC/PPCTargetTransformInfo.cpp | 253 +- lib/Target/PowerPC/PPCTargetTransformInfo.h | 103 + lib/Target/PowerPC/PPCVSXCopy.cpp | 176 + lib/Target/PowerPC/PPCVSXFMAMutate.cpp | 335 + lib/Target/PowerPC/README.txt | 275 - lib/Target/R600/AMDGPU.h | 16 +- lib/Target/R600/AMDGPU.td | 17 + lib/Target/R600/AMDGPUAsmPrinter.cpp | 288 +- lib/Target/R600/AMDGPUAsmPrinter.h | 31 +- lib/Target/R600/AMDGPUISelDAGToDAG.cpp | 231 +- lib/Target/R600/AMDGPUISelLowering.cpp | 480 +- lib/Target/R600/AMDGPUISelLowering.h | 40 +- lib/Target/R600/AMDGPUInstrInfo.cpp | 40 +- lib/Target/R600/AMDGPUInstrInfo.h | 11 + lib/Target/R600/AMDGPUInstrInfo.td | 18 +- lib/Target/R600/AMDGPUInstructions.td | 73 +- lib/Target/R600/AMDGPUMCInstLower.cpp | 51 +- lib/Target/R600/AMDGPUMCInstLower.h | 13 - lib/Target/R600/AMDGPUMachineFunction.cpp | 4 +- lib/Target/R600/AMDGPURegisterInfo.cpp | 3 +- lib/Target/R600/AMDGPUSubtarget.cpp | 75 +- lib/Target/R600/AMDGPUSubtarget.h | 42 +- lib/Target/R600/AMDGPUTargetMachine.cpp | 217 +- lib/Target/R600/AMDGPUTargetMachine.h | 45 +- lib/Target/R600/AMDGPUTargetTransformInfo.cpp | 94 +- lib/Target/R600/AMDGPUTargetTransformInfo.h | 78 + lib/Target/R600/AMDKernelCodeT.h | 704 + lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 32 +- lib/Target/R600/CIInstructions.td | 42 + lib/Target/R600/CMakeLists.txt | 2 + lib/Target/R600/CaymanInstructions.td | 4 +- lib/Target/R600/EvergreenInstructions.td | 14 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.cpp | 71 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.h | 3 +- lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp | 2 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 1 + .../R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 10 + lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.h | 1 + lib/Target/R600/MCTargetDesc/R600MCCodeEmitter.cpp | 4 +- lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp | 149 +- lib/Target/R600/Processors.td | 38 +- lib/Target/R600/R600ControlFlowFinalizer.cpp | 46 +- lib/Target/R600/R600ISelLowering.cpp | 62 +- lib/Target/R600/R600ISelLowering.h | 2 +- lib/Target/R600/R600Instructions.td | 36 +- lib/Target/R600/R600MachineScheduler.cpp | 7 +- lib/Target/R600/R600Packetizer.cpp | 2 +- lib/Target/R600/R700Instructions.td | 2 +- lib/Target/R600/SIAnnotateControlFlow.cpp | 27 +- lib/Target/R600/SIDefines.h | 72 +- lib/Target/R600/SIFixSGPRCopies.cpp | 36 +- lib/Target/R600/SIFoldOperands.cpp | 287 + lib/Target/R600/SIISelLowering.cpp | 867 +- lib/Target/R600/SIISelLowering.h | 20 +- lib/Target/R600/SIInsertWaits.cpp | 117 +- lib/Target/R600/SIInstrFormats.td | 429 +- lib/Target/R600/SIInstrInfo.cpp | 621 +- lib/Target/R600/SIInstrInfo.h | 128 +- lib/Target/R600/SIInstrInfo.td | 1442 +- lib/Target/R600/SIInstructions.td | 1846 +- lib/Target/R600/SILoadStoreOptimizer.cpp | 43 +- lib/Target/R600/SILowerControlFlow.cpp | 44 +- lib/Target/R600/SILowerI1Copies.cpp | 78 +- lib/Target/R600/SIMachineFunctionInfo.cpp | 9 +- lib/Target/R600/SIMachineFunctionInfo.h | 4 + lib/Target/R600/SIPrepareScratchRegs.cpp | 208 + lib/Target/R600/SIRegisterInfo.cpp | 247 +- lib/Target/R600/SIRegisterInfo.h | 39 +- lib/Target/R600/SIRegisterInfo.td | 50 +- lib/Target/R600/SISchedule.td | 80 +- lib/Target/R600/SIShrinkInstructions.cpp | 37 +- lib/Target/R600/SITypeRewriter.cpp | 3 +- lib/Target/R600/TargetInfo/AMDGPUTargetInfo.cpp | 6 +- lib/Target/R600/VIInstrFormats.td | 166 + lib/Target/R600/VIInstructions.td | 25 + lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 5 +- lib/Target/Sparc/DelaySlotFiller.cpp | 17 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 4 +- .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 4 +- lib/Target/Sparc/SparcAsmPrinter.cpp | 12 +- lib/Target/Sparc/SparcFrameLowering.cpp | 7 +- lib/Target/Sparc/SparcISelDAGToDAG.cpp | 15 +- lib/Target/Sparc/SparcISelLowering.cpp | 52 +- lib/Target/Sparc/SparcISelLowering.h | 8 +- lib/Target/Sparc/SparcInstrInfo.td | 18 +- lib/Target/Sparc/SparcSubtarget.cpp | 30 +- lib/Target/Sparc/SparcSubtarget.h | 2 - lib/Target/Sparc/SparcTargetMachine.cpp | 37 +- lib/Target/Sparc/SparcTargetMachine.h | 2 + lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 94 +- lib/Target/SystemZ/CMakeLists.txt | 1 + .../SystemZ/InstPrinter/SystemZInstPrinter.cpp | 24 + .../SystemZ/InstPrinter/SystemZInstPrinter.h | 1 + .../SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp | 8 +- .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 2 + .../SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp | 34 +- lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h | 3 +- .../SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp | 48 +- lib/Target/SystemZ/SystemZ.h | 1 + lib/Target/SystemZ/SystemZAsmPrinter.cpp | 46 +- lib/Target/SystemZ/SystemZAsmPrinter.h | 9 +- lib/Target/SystemZ/SystemZConstantPoolValue.cpp | 5 + lib/Target/SystemZ/SystemZConstantPoolValue.h | 8 +- lib/Target/SystemZ/SystemZElimCompare.cpp | 2 +- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 16 +- lib/Target/SystemZ/SystemZISelLowering.cpp | 193 +- lib/Target/SystemZ/SystemZISelLowering.h | 16 +- lib/Target/SystemZ/SystemZInstrFP.td | 4 +- lib/Target/SystemZ/SystemZInstrInfo.cpp | 2 +- lib/Target/SystemZ/SystemZInstrInfo.h | 7 +- lib/Target/SystemZ/SystemZInstrInfo.td | 46 +- lib/Target/SystemZ/SystemZLDCleanup.cpp | 143 + lib/Target/SystemZ/SystemZMCInstLower.cpp | 2 + lib/Target/SystemZ/SystemZMachineFunctionInfo.h | 8 +- lib/Target/SystemZ/SystemZOperands.td | 30 + lib/Target/SystemZ/SystemZOperators.td | 7 + lib/Target/SystemZ/SystemZProcessors.td | 4 +- lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp | 11 +- lib/Target/SystemZ/SystemZSubtarget.cpp | 9 +- lib/Target/SystemZ/SystemZSubtarget.h | 2 - lib/Target/SystemZ/SystemZTargetMachine.cpp | 22 +- lib/Target/SystemZ/SystemZTargetMachine.h | 2 + lib/Target/Target.cpp | 17 +- lib/Target/TargetLibraryInfo.cpp | 753 - lib/Target/TargetLoweringObjectFile.cpp | 31 +- lib/Target/TargetMachine.cpp | 51 +- lib/Target/TargetMachineC.cpp | 14 +- lib/Target/X86/Android.mk | 1 + lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp | 102 +- lib/Target/X86/AsmParser/X86AsmParser.cpp | 221 +- lib/Target/X86/AsmParser/X86AsmParserCommon.h | 5 + lib/Target/X86/AsmParser/X86Operand.h | 75 +- lib/Target/X86/CMakeLists.txt | 3 +- lib/Target/X86/Disassembler/X86Disassembler.cpp | 290 +- .../X86/Disassembler/X86DisassemblerDecoder.cpp | 63 +- .../X86/Disassembler/X86DisassemblerDecoder.h | 19 +- .../Disassembler/X86DisassemblerDecoderCommon.h | 31 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 60 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.h | 13 +- lib/Target/X86/InstPrinter/X86InstComments.cpp | 1706 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp | 63 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.h | 13 +- lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 37 +- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 80 +- lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 3 + lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 12 +- lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h | 3 +- lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 126 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 19 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 4 +- .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 120 +- .../X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp | 6 +- lib/Target/X86/TargetInfo/X86TargetInfo.cpp | 2 +- lib/Target/X86/Utils/X86ShuffleDecode.cpp | 829 +- lib/Target/X86/Utils/X86ShuffleDecode.h | 198 +- lib/Target/X86/X86.h | 8 +- lib/Target/X86/X86.td | 238 +- lib/Target/X86/X86AsmPrinter.cpp | 41 +- lib/Target/X86/X86AsmPrinter.h | 8 +- lib/Target/X86/X86CallFrameOptimization.cpp | 480 + lib/Target/X86/X86CallingConv.td | 11 + lib/Target/X86/X86FastISel.cpp | 358 +- lib/Target/X86/X86FixupLEAs.cpp | 14 +- lib/Target/X86/X86FloatingPoint.cpp | 10 +- lib/Target/X86/X86FrameLowering.cpp | 827 +- lib/Target/X86/X86FrameLowering.h | 28 +- lib/Target/X86/X86ISelDAGToDAG.cpp | 69 +- lib/Target/X86/X86ISelLowering.cpp | 15534 +++++------- lib/Target/X86/X86ISelLowering.h | 65 +- lib/Target/X86/X86InstrAVX512.td | 1945 +- lib/Target/X86/X86InstrArithmetic.td | 331 +- lib/Target/X86/X86InstrCompiler.td | 260 +- lib/Target/X86/X86InstrControl.td | 129 +- lib/Target/X86/X86InstrExtension.td | 16 +- lib/Target/X86/X86InstrFMA.td | 6 +- lib/Target/X86/X86InstrFPStack.td | 84 +- lib/Target/X86/X86InstrFormats.td | 165 +- lib/Target/X86/X86InstrFragmentsSIMD.td | 140 +- lib/Target/X86/X86InstrInfo.cpp | 1433 +- lib/Target/X86/X86InstrInfo.h | 6 + lib/Target/X86/X86InstrInfo.td | 832 +- lib/Target/X86/X86InstrMMX.td | 88 +- lib/Target/X86/X86InstrSGX.td | 4 +- lib/Target/X86/X86InstrSSE.td | 2681 +- lib/Target/X86/X86InstrShiftRotate.td | 58 +- lib/Target/X86/X86InstrSystem.td | 66 +- lib/Target/X86/X86InstrTSX.td | 9 +- lib/Target/X86/X86InstrXOP.td | 206 +- lib/Target/X86/X86IntrinsicsInfo.h | 314 +- lib/Target/X86/X86MCInstLower.cpp | 138 +- lib/Target/X86/X86MachineFunctionInfo.cpp | 19 + lib/Target/X86/X86MachineFunctionInfo.h | 48 +- lib/Target/X86/X86PadShortFunction.cpp | 20 +- lib/Target/X86/X86RegisterInfo.cpp | 40 +- lib/Target/X86/X86RegisterInfo.h | 1 + lib/Target/X86/X86RegisterInfo.td | 44 +- lib/Target/X86/X86SchedHaswell.td | 2 +- lib/Target/X86/X86SelectionDAGInfo.cpp | 17 +- lib/Target/X86/X86Subtarget.cpp | 56 +- lib/Target/X86/X86Subtarget.h | 166 +- lib/Target/X86/X86TargetMachine.cpp | 99 +- lib/Target/X86/X86TargetMachine.h | 16 +- lib/Target/X86/X86TargetObjectFile.cpp | 16 + lib/Target/X86/X86TargetObjectFile.h | 6 + lib/Target/X86/X86TargetTransformInfo.cpp | 348 +- lib/Target/X86/X86TargetTransformInfo.h | 112 + lib/Target/X86/X86VZeroUpper.cpp | 32 +- lib/Target/XCore/CMakeLists.txt | 1 - lib/Target/XCore/XCore.h | 2 - lib/Target/XCore/XCoreAsmPrinter.cpp | 13 +- lib/Target/XCore/XCoreFrameLowering.cpp | 9 +- lib/Target/XCore/XCoreISelDAGToDAG.cpp | 4 +- lib/Target/XCore/XCoreISelLowering.cpp | 44 +- lib/Target/XCore/XCoreISelLowering.h | 9 +- lib/Target/XCore/XCoreInstrInfo.td | 34 +- lib/Target/XCore/XCoreLowerThreadLocal.cpp | 2 +- lib/Target/XCore/XCoreSubtarget.cpp | 5 +- lib/Target/XCore/XCoreSubtarget.h | 2 - lib/Target/XCore/XCoreTargetMachine.cpp | 20 +- lib/Target/XCore/XCoreTargetMachine.h | 4 +- lib/Target/XCore/XCoreTargetObjectFile.cpp | 96 +- lib/Target/XCore/XCoreTargetTransformInfo.cpp | 80 - lib/Target/XCore/XCoreTargetTransformInfo.h | 72 + lib/Transforms/IPO/Android.mk | 1 + lib/Transforms/IPO/ArgumentPromotion.cpp | 6 +- lib/Transforms/IPO/CMakeLists.txt | 5 + lib/Transforms/IPO/DeadArgumentElimination.cpp | 161 +- lib/Transforms/IPO/FunctionAttrs.cpp | 8 +- lib/Transforms/IPO/GlobalDCE.cpp | 3 + lib/Transforms/IPO/GlobalOpt.cpp | 8 +- lib/Transforms/IPO/IPO.cpp | 3 +- lib/Transforms/IPO/InlineAlways.cpp | 4 +- lib/Transforms/IPO/InlineSimple.cpp | 4 +- lib/Transforms/IPO/Inliner.cpp | 53 +- lib/Transforms/IPO/LLVMBuild.txt | 2 +- lib/Transforms/IPO/LoopExtractor.cpp | 2 +- lib/Transforms/IPO/LowerBitSets.cpp | 612 + lib/Transforms/IPO/PartialInlining.cpp | 10 +- lib/Transforms/IPO/PassManagerBuilder.cpp | 53 +- lib/Transforms/IPO/PruneEH.cpp | 8 +- lib/Transforms/IPO/StripSymbols.cpp | 4 +- lib/Transforms/InstCombine/CMakeLists.txt | 4 + lib/Transforms/InstCombine/InstCombine.h | 432 - lib/Transforms/InstCombine/InstCombineAddSub.cpp | 126 +- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 216 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 310 +- lib/Transforms/InstCombine/InstCombineCasts.cpp | 85 +- lib/Transforms/InstCombine/InstCombineCompares.cpp | 309 +- lib/Transforms/InstCombine/InstCombineInternal.h | 529 + .../InstCombine/InstCombineLoadStoreAlloca.cpp | 469 +- .../InstCombine/InstCombineMulDivRem.cpp | 174 +- lib/Transforms/InstCombine/InstCombinePHI.cpp | 4 +- lib/Transforms/InstCombine/InstCombineSelect.cpp | 261 +- lib/Transforms/InstCombine/InstCombineShifts.cpp | 16 +- .../InstCombine/InstCombineSimplifyDemanded.cpp | 2 +- .../InstCombine/InstCombineVectorOps.cpp | 123 +- lib/Transforms/InstCombine/InstCombineWorklist.h | 107 - .../InstCombine/InstructionCombining.cpp | 572 +- lib/Transforms/InstCombine/LLVMBuild.txt | 2 +- .../Instrumentation/AddressSanitizer.cpp | 587 +- lib/Transforms/Instrumentation/Android.mk | 2 +- lib/Transforms/Instrumentation/BoundsChecking.cpp | 6 +- lib/Transforms/Instrumentation/CMakeLists.txt | 5 +- .../Instrumentation/DataFlowSanitizer.cpp | 63 +- lib/Transforms/Instrumentation/DebugIR.cpp | 617 - lib/Transforms/Instrumentation/DebugIR.h | 98 - lib/Transforms/Instrumentation/GCOVProfiling.cpp | 43 +- lib/Transforms/Instrumentation/InstrProfiling.cpp | 351 + lib/Transforms/Instrumentation/Instrumentation.cpp | 1 + lib/Transforms/Instrumentation/LLVMBuild.txt | 2 +- lib/Transforms/Instrumentation/MemorySanitizer.cpp | 526 +- .../Instrumentation/SanitizerCoverage.cpp | 175 +- lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 40 +- lib/Transforms/ObjCARC/ARCInstKind.cpp | 645 + lib/Transforms/ObjCARC/ARCInstKind.h | 123 + lib/Transforms/ObjCARC/Android.mk | 2 +- lib/Transforms/ObjCARC/CMakeLists.txt | 5 +- lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 81 +- lib/Transforms/ObjCARC/DependencyAnalysis.h | 21 +- lib/Transforms/ObjCARC/ObjCARC.h | 211 +- lib/Transforms/ObjCARC/ObjCARCAPElim.cpp | 8 +- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp | 26 +- lib/Transforms/ObjCARC/ObjCARCContract.cpp | 494 +- lib/Transforms/ObjCARC/ObjCARCExpand.cpp | 14 +- lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 240 +- lib/Transforms/ObjCARC/ObjCARCUtil.cpp | 254 - lib/Transforms/ObjCARC/ProvenanceAnalysis.h | 4 +- lib/Transforms/Scalar/ADCE.cpp | 70 +- lib/Transforms/Scalar/AlignmentFromAssumptions.cpp | 16 +- lib/Transforms/Scalar/Android.mk | 6 + lib/Transforms/Scalar/BDCE.cpp | 411 + lib/Transforms/Scalar/CMakeLists.txt | 10 + lib/Transforms/Scalar/ConstantHoisting.cpp | 9 +- lib/Transforms/Scalar/ConstantProp.cpp | 9 +- lib/Transforms/Scalar/DCE.cpp | 8 +- lib/Transforms/Scalar/DeadStoreElimination.cpp | 2 +- lib/Transforms/Scalar/EarlyCSE.cpp | 635 +- lib/Transforms/Scalar/GVN.cpp | 516 +- lib/Transforms/Scalar/IndVarSimplify.cpp | 14 +- .../Scalar/InductiveRangeCheckElimination.cpp | 1422 ++ lib/Transforms/Scalar/JumpThreading.cpp | 30 +- lib/Transforms/Scalar/LICM.cpp | 401 +- lib/Transforms/Scalar/LLVMBuild.txt | 2 +- lib/Transforms/Scalar/LoopDeletion.cpp | 8 +- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 98 +- lib/Transforms/Scalar/LoopInstSimplify.cpp | 29 +- lib/Transforms/Scalar/LoopRerollPass.cpp | 1285 +- lib/Transforms/Scalar/LoopRotation.cpp | 98 +- lib/Transforms/Scalar/LoopStrengthReduce.cpp | 36 +- lib/Transforms/Scalar/LoopUnrollPass.cpp | 495 +- lib/Transforms/Scalar/LoopUnswitch.cpp | 70 +- lib/Transforms/Scalar/LowerExpectIntrinsic.cpp | 192 + lib/Transforms/Scalar/MemCpyOptimizer.cpp | 32 +- lib/Transforms/Scalar/MergedLoadStoreMotion.cpp | 83 +- lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp | 14 +- lib/Transforms/Scalar/PlaceSafepoints.cpp | 989 + lib/Transforms/Scalar/Reassociate.cpp | 15 +- lib/Transforms/Scalar/Reg2Mem.cpp | 2 +- lib/Transforms/Scalar/RewriteStatepointsForGC.cpp | 1897 ++ lib/Transforms/Scalar/SCCP.cpp | 14 +- lib/Transforms/Scalar/SROA.cpp | 1501 +- lib/Transforms/Scalar/SampleProfile.cpp | 6 +- lib/Transforms/Scalar/Scalar.cpp | 15 +- lib/Transforms/Scalar/ScalarReplAggregates.cpp | 31 +- .../Scalar/SeparateConstOffsetFromGEP.cpp | 14 +- lib/Transforms/Scalar/SimplifyCFGPass.cpp | 118 +- lib/Transforms/Scalar/Sink.cpp | 8 +- .../Scalar/StraightLineStrengthReduce.cpp | 274 + lib/Transforms/Scalar/StructurizeCFG.cpp | 75 +- lib/Transforms/Scalar/TailRecursionElimination.cpp | 6 +- lib/Transforms/Utils/ASanStackFrameLayout.cpp | 8 +- lib/Transforms/Utils/AddDiscriminators.cpp | 2 +- lib/Transforms/Utils/Android.mk | 1 - lib/Transforms/Utils/BasicBlockUtils.cpp | 211 +- lib/Transforms/Utils/BreakCriticalEdges.cpp | 63 +- lib/Transforms/Utils/BuildLibCalls.cpp | 134 +- lib/Transforms/Utils/CMakeLists.txt | 5 +- lib/Transforms/Utils/CloneFunction.cpp | 158 +- lib/Transforms/Utils/CloneModule.cpp | 4 +- lib/Transforms/Utils/DemoteRegToStack.cpp | 34 +- lib/Transforms/Utils/InlineFunction.cpp | 136 +- lib/Transforms/Utils/LCSSA.cpp | 55 +- lib/Transforms/Utils/LLVMBuild.txt | 2 +- lib/Transforms/Utils/Local.cpp | 85 +- lib/Transforms/Utils/LoopSimplify.cpp | 91 +- lib/Transforms/Utils/LoopUnroll.cpp | 40 +- lib/Transforms/Utils/LoopUnrollRuntime.cpp | 104 +- lib/Transforms/Utils/LowerExpectIntrinsic.cpp | 188 - lib/Transforms/Utils/LowerSwitch.cpp | 272 +- lib/Transforms/Utils/Mem2Reg.cpp | 11 +- lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 19 +- lib/Transforms/Utils/SSAUpdater.cpp | 41 +- lib/Transforms/Utils/SimplifyCFG.cpp | 600 +- lib/Transforms/Utils/SimplifyIndVar.cpp | 129 +- lib/Transforms/Utils/SimplifyInstructions.cpp | 20 +- lib/Transforms/Utils/SimplifyLibCalls.cpp | 677 +- lib/Transforms/Utils/SymbolRewriter.cpp | 33 +- lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | 1 - lib/Transforms/Utils/ValueMapper.cpp | 255 +- lib/Transforms/Vectorize/BBVectorize.cpp | 22 +- lib/Transforms/Vectorize/CMakeLists.txt | 3 + lib/Transforms/Vectorize/LLVMBuild.txt | 2 +- lib/Transforms/Vectorize/LoopVectorize.cpp | 1882 +- lib/Transforms/Vectorize/SLPVectorizer.cpp | 552 +- lib/Transforms/Vectorize/Vectorize.cpp | 2 +- shared_llvm.mk | 6 +- test/Analysis/AssumptionCache/basic.ll | 22 + test/Analysis/BasicAA/2003-11-04-SimpleCases.ll | 4 +- test/Analysis/BasicAA/2003-12-11-ConstExprGEP.ll | 4 +- test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll | 6 +- test/Analysis/BasicAA/constant-over-index.ll | 7 +- test/Analysis/BasicAA/full-store-partial-alias.ll | 12 +- test/Analysis/BasicAA/invariant_load.ll | 2 +- test/Analysis/BasicAA/struct-geps.ll | 164 + test/Analysis/BlockFrequencyInfo/bad_input.ll | 4 +- test/Analysis/BlockFrequencyInfo/basic.ll | 6 +- .../Analysis/BlockFrequencyInfo/double_backedge.ll | 4 +- test/Analysis/BlockFrequencyInfo/double_exit.ll | 8 +- .../extremely-likely-loop-successor.ll | 40 + test/Analysis/BlockFrequencyInfo/irreducible.ll | 48 +- .../BlockFrequencyInfo/loop_with_branch.ll | 4 +- .../nested_loop_with_branches.ll | 4 +- test/Analysis/BranchProbabilityInfo/basic.ll | 6 +- .../Analysis/CFLAliasAnalysis/asm-global-bugfix.ll | 16 + .../CFLAliasAnalysis/full-store-partial-alias.ll | 20 +- .../CFLAliasAnalysis/gep-signed-arithmetic.ll | 6 +- test/Analysis/CFLAliasAnalysis/must-and-partial.ll | 25 +- .../CFLAliasAnalysis/stratified-attrs-indexing.ll | 33 + .../CostModel/X86/masked-intrinsic-cost.ll | 89 + test/Analysis/CostModel/X86/vselect-cost.ll | 28 +- test/Analysis/CostModel/no_info.ll | 7 +- test/Analysis/Dominators/basic.ll | 60 + test/Analysis/Lint/cppeh-catch-intrinsics-clean.ll | 109 + test/Analysis/Lint/cppeh-catch-intrinsics.ll | 278 + .../backward-dep-different-types.ll | 50 + .../unsafe-and-rt-checks-no-dbg.ll | 60 + .../LoopAccessAnalysis/unsafe-and-rt-checks.ll | 61 + .../Analysis/LoopInfo/2003-05-15-NestingProblem.ll | 1 + test/Analysis/ScalarEvolution/incorrect-nsw.ll | 26 + .../ScalarEvolution/infer-prestart-no-wrap.ll | 101 + .../ScalarEvolution/load-with-range-metadata.ll | 2 +- test/Analysis/ScalarEvolution/min-max-exprs.ll | 53 + .../ScalarEvolution/nw-sub-is-not-nw-add.ll | 41 + test/Analysis/ScalarEvolution/pr22179.ll | 28 + test/Analysis/ScalarEvolution/pr22641.ll | 25 + test/Analysis/ScalarEvolution/pr22674.ll | 101 + .../scev-expander-incorrect-nowrap.ll | 30 + .../ScalarEvolution/scev-prestart-nowrap.ll | 82 + .../Analysis/ScalarEvolution/zext-signed-addrec.ll | 2 +- test/Analysis/ScopedNoAliasAA/basic-domains.ll | 20 +- test/Analysis/ScopedNoAliasAA/basic.ll | 4 +- test/Analysis/ScopedNoAliasAA/basic2.ll | 12 +- test/Analysis/TypeBasedAliasAnalysis/PR17620.ll | 22 +- test/Analysis/TypeBasedAliasAnalysis/aliastest.ll | 24 +- .../TypeBasedAliasAnalysis/argument-promotion.ll | 10 +- test/Analysis/TypeBasedAliasAnalysis/dse.ll | 24 +- .../TypeBasedAliasAnalysis/dynamic-indices.ll | 24 +- .../TypeBasedAliasAnalysis/functionattrs.ll | 8 +- .../gvn-nonlocal-type-mismatch.ll | 32 +- test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll | 10 +- test/Analysis/TypeBasedAliasAnalysis/licm.ll | 20 +- test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll | 14 +- .../TypeBasedAliasAnalysis/placement-tbaa.ll | 22 +- test/Analysis/TypeBasedAliasAnalysis/precedence.ll | 18 +- test/Analysis/TypeBasedAliasAnalysis/sink.ll | 14 +- test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll | 54 +- .../ValueTracking/memory-dereferenceable.ll | 34 + .../2010-02-05-FunctionLocalMetadataBecomesNull.ll | 28 +- test/Assembler/ConstantExprNoFold.ll | 11 + test/Assembler/alloca-invalid-type-2.ll | 9 + test/Assembler/alloca-invalid-type.ll | 9 + test/Assembler/call-invalid-1.ll | 9 + test/Assembler/debug-info.ll | 72 + test/Assembler/distinct-mdnode.ll | 28 + test/Assembler/drop-debug-info.ll | 29 + test/Assembler/extractvalue-no-idx.ll | 8 + test/Assembler/functionlocal-metadata.ll | 60 +- test/Assembler/generic-debug-node.ll | 27 + test/Assembler/getelementptr.ll | 6 + test/Assembler/getelementptr_vec_idx4.ll | 5 + test/Assembler/gv-invalid-type.ll | 4 + test/Assembler/inalloca.ll | 2 +- test/Assembler/insertvalue-invalid-type-1.ll | 7 + test/Assembler/insertvalue-invalid-type.ll | 9 + test/Assembler/invalid-attrgrp.ll | 4 + test/Assembler/invalid-comdat.ll | 2 +- test/Assembler/invalid-datalayout1.ll | 3 + test/Assembler/invalid-datalayout10.ll | 3 + test/Assembler/invalid-datalayout11.ll | 3 + test/Assembler/invalid-datalayout12.ll | 3 + test/Assembler/invalid-datalayout13.ll | 3 + test/Assembler/invalid-datalayout14.ll | 3 + test/Assembler/invalid-datalayout15.ll | 3 + test/Assembler/invalid-datalayout16.ll | 3 + test/Assembler/invalid-datalayout17.ll | 3 + test/Assembler/invalid-datalayout18.ll | 3 + test/Assembler/invalid-datalayout2.ll | 3 + test/Assembler/invalid-datalayout3.ll | 3 + test/Assembler/invalid-datalayout4.ll | 3 + test/Assembler/invalid-datalayout5.ll | 3 + test/Assembler/invalid-datalayout6.ll | 3 + test/Assembler/invalid-datalayout7.ll | 3 + test/Assembler/invalid-datalayout8.ll | 3 + test/Assembler/invalid-datalayout9.ll | 3 + test/Assembler/invalid-debug-info-version.ll | 5 + test/Assembler/invalid-fwdref2.ll | 4 + .../invalid-generic-debug-node-tag-bad.ll | 4 + .../invalid-generic-debug-node-tag-missing.ll | 4 + .../invalid-generic-debug-node-tag-overflow.ll | 7 + .../invalid-generic-debug-node-tag-wrong-type.ll | 4 + test/Assembler/invalid-hexint.ll | 4 + test/Assembler/invalid-mdbasictype-missing-tag.ll | 4 + .../invalid-mdcompileunit-language-bad.ll | 5 + .../invalid-mdcompileunit-language-overflow.ll | 9 + .../invalid-mdcompileunit-missing-language.ll | 4 + .../invalid-mdcompositetype-missing-tag.ll | 4 + .../invalid-mdderivedtype-missing-basetype.ll | 4 + .../Assembler/invalid-mdderivedtype-missing-tag.ll | 4 + .../Assembler/invalid-mdenumerator-missing-name.ll | 4 + .../invalid-mdenumerator-missing-value.ll | 4 + test/Assembler/invalid-mdexpression-large.ll | 7 + test/Assembler/invalid-mdexpression-verify.ll | 9 + test/Assembler/invalid-mdfile-missing-directory.ll | 4 + test/Assembler/invalid-mdfile-missing-filename.ll | 4 + .../invalid-mdglobalvariable-missing-name.ll | 4 + .../invalid-mdimportedentity-missing-parent.ll | 4 + .../invalid-mdimportedentity-missing-tag.ll | 4 + .../invalid-mdlexicalblock-missing-parent.ll | 4 + ...lid-mdlexicalblockfile-missing-discriminator.ll | 4 + .../invalid-mdlexicalblockfile-missing-parent.ll | 4 + .../invalid-mdlocalvariable-missing-name.ll | 4 + test/Assembler/invalid-mdlocation-field-bad.ll | 4 + test/Assembler/invalid-mdlocation-field-twice.ll | 6 + .../invalid-mdlocation-missing-scope-2.ll | 4 + test/Assembler/invalid-mdlocation-missing-scope.ll | 4 + .../invalid-mdlocation-overflow-column.ll | 9 + test/Assembler/invalid-mdlocation-overflow-line.ll | 9 + .../invalid-mdnamespace-missing-namespace.ll | 4 + test/Assembler/invalid-mdnode-badref.ll | 5 + test/Assembler/invalid-mdnode-vector.ll | 4 + test/Assembler/invalid-mdnode-vector2.ll | 4 + .../invalid-mdobjcproperty-missing-name.ll | 4 + .../Assembler/invalid-mdsubprogram-missing-name.ll | 4 + test/Assembler/invalid-mdsubrange-count-large.ll | 7 + test/Assembler/invalid-mdsubrange-count-missing.ll | 4 + .../Assembler/invalid-mdsubrange-count-negative.ll | 7 + .../Assembler/invalid-mdsubrange-lowerBound-max.ll | 4 + .../Assembler/invalid-mdsubrange-lowerBound-min.ll | 4 + .../invalid-mdsubroutinetype-missing-types.ll | 4 + ...invalid-mdtemplatetypeparameter-missing-type.ll | 4 + ...invalid-mdtemplatevalueparameter-missing-tag.ll | 4 + ...nvalid-mdtemplatevalueparameter-missing-type.ll | 5 + ...valid-mdtemplatevalueparameter-missing-value.ll | 5 + .../invalid-metadata-attachment-has-type.ll | 8 + .../invalid-metadata-function-local-attachments.ll | 7 + .../invalid-metadata-function-local-complex-1.ll | 10 + .../invalid-metadata-function-local-complex-2.ll | 10 + .../invalid-metadata-function-local-complex-3.ll | 10 + test/Assembler/invalid-metadata-has-type.ll | 5 + test/Assembler/invalid-name.ll | Bin 117 -> 142 bytes test/Assembler/invalid-name2.ll | Bin 0 -> 120 bytes test/Assembler/invalid-specialized-mdnode.ll | 4 + test/Assembler/invalid_cast4.ll | 4 + test/Assembler/large-comdat.ll | 9 + test/Assembler/mdcompileunit.ll | 31 + test/Assembler/mdexpression.ll | 16 + test/Assembler/mdglobalvariable.ll | 22 + test/Assembler/mdimportedentity.ll | 20 + test/Assembler/mdlexicalblock.ll | 25 + test/Assembler/mdlocalvariable.ll | 26 + test/Assembler/mdlocation.ll | 23 + test/Assembler/mdnamespace.ll | 16 + test/Assembler/mdobjcproperty.ll | 20 + test/Assembler/mdsubprogram.ll | 28 + test/Assembler/mdsubrange-empty-array.ll | 14 + test/Assembler/mdtemplateparameter.ll | 24 + test/Assembler/mdtype-large-values.ll | 12 + test/Assembler/metadata-null-operands.ll | 13 + test/Assembler/metadata.ll | 4 +- test/Assembler/named-metadata.ll | 6 +- test/Assembler/short-hexpair.ll | 4 + test/Assembler/unnamed-comdat.ll | 6 + test/Assembler/upgrade-loop-metadata.ll | 16 +- test/Bindings/Go/go.test | 2 +- test/Bindings/OCaml/core.ml | 17 +- test/Bindings/OCaml/executionengine.ml | 11 +- test/Bindings/OCaml/linker.ml | 6 +- test/Bindings/OCaml/lit.local.cfg | 2 +- test/Bindings/OCaml/transform_utils.ml | 21 + test/Bindings/llvm-c/Inputs/invalid.ll.bc | Bin 0 -> 332 bytes test/Bindings/llvm-c/add_named_metadata_operand.ll | 2 + test/Bindings/llvm-c/invalid-bitcode.test | 3 + test/Bindings/llvm-c/set_metadata.ll | 2 + test/Bitcode/Inputs/invalid-abbrev.bc | Bin 0 -> 129 bytes test/Bitcode/Inputs/invalid-align.bc | Bin 0 -> 428 bytes test/Bitcode/Inputs/invalid-bad-abbrev-number.bc | 1 + test/Bitcode/Inputs/invalid-bitwidth.bc | Bin 0 -> 224 bytes .../Bitcode/Inputs/invalid-extractval-array-idx.bc | Bin 0 -> 450 bytes .../Inputs/invalid-extractval-struct-idx.bc | Bin 0 -> 444 bytes .../Inputs/invalid-extractval-too-many-idxs.bc | Bin 0 -> 452 bytes test/Bitcode/Inputs/invalid-insertval-array-idx.bc | Bin 0 -> 452 bytes .../Bitcode/Inputs/invalid-insertval-struct-idx.bc | Bin 0 -> 444 bytes .../Inputs/invalid-insertval-too-many-idxs.bc | Bin 0 -> 452 bytes test/Bitcode/Inputs/invalid-pr20485.bc | Bin 0 -> 272 bytes .../Inputs/invalid-type-table-forward-ref.bc | Bin 0 -> 452 bytes test/Bitcode/Inputs/invalid-unexpected-eof.bc | 1 + test/Bitcode/calling-conventions.3.2.ll | 4 +- test/Bitcode/drop-debug-info.3.5.ll | 40 + test/Bitcode/drop-debug-info.3.5.ll.bc | Bin 0 -> 1264 bytes test/Bitcode/drop-debug-info.ll | 29 - test/Bitcode/function-encoding-rel-operands.ll | 4 +- test/Bitcode/function-local-metadata.3.5.ll | 35 + test/Bitcode/function-local-metadata.3.5.ll.bc | Bin 0 -> 396 bytes test/Bitcode/highLevelStructure.3.2.ll | 6 +- test/Bitcode/invalid.ll | 2 +- test/Bitcode/invalid.test | 43 + test/Bitcode/linkage-types-3.2.ll | 82 +- test/Bitcode/mdstring-high-bits.ll | 9 + test/Bitcode/metadata-2.ll | 4 +- test/Bitcode/metadata.3.5.ll | 26 + test/Bitcode/metadata.3.5.ll.bc | Bin 0 -> 432 bytes test/Bitcode/metadata.ll | 2 +- test/Bitcode/pr18704.ll | 2 +- test/Bitcode/upgrade-loop-metadata.ll | 6 +- test/Bitcode/upgrade-tbaa.ll | 18 +- test/Bitcode/weak-macho-3.5.ll | 11 + test/Bitcode/weak-macho-3.5.ll.bc | Bin 0 -> 352 bytes test/BugPoint/metadata.ll | 38 +- test/CMakeLists.txt | 23 +- .../aarch64-2014-08-11-MachineCombinerCrash.ll | 122 +- .../AArch64/aarch64-2014-12-02-combine-soften.ll | 16 + test/CodeGen/AArch64/addsub-shifted.ll | 14 +- test/CodeGen/AArch64/analyze-branch.ll | 4 +- test/CodeGen/AArch64/analyzecmp.ll | 8 +- test/CodeGen/AArch64/argument-blocks.ll | 197 + .../AArch64/arm64-2011-03-17-AsmPrinterCrash.ll | 46 +- .../CodeGen/AArch64/arm64-2012-05-22-LdStOptBug.ll | 10 +- test/CodeGen/AArch64/arm64-2012-06-06-FPToUI.ll | 8 +- test/CodeGen/AArch64/arm64-aapcs-be.ll | 18 +- test/CodeGen/AArch64/arm64-abi_align.ll | 10 +- test/CodeGen/AArch64/arm64-atomic-128.ll | 24 +- test/CodeGen/AArch64/arm64-ccmp-heuristics.ll | 8 +- test/CodeGen/AArch64/arm64-cse.ll | 2 +- test/CodeGen/AArch64/arm64-fastcc-tailcall.ll | 6 +- .../arm64-fixed-point-scalar-cvt-dagcombine.ll | 2 +- test/CodeGen/AArch64/arm64-fold-address.ll | 10 +- .../CodeGen/AArch64/arm64-indexed-vector-ldst-2.ll | 8 +- test/CodeGen/AArch64/arm64-ldp.ll | 85 + test/CodeGen/AArch64/arm64-named-reg-alloc.ll | 2 +- test/CodeGen/AArch64/arm64-named-reg-notareg.ll | 2 +- test/CodeGen/AArch64/arm64-neon-copy.ll | 2 +- test/CodeGen/AArch64/arm64-neon-select_cc.ll | 15 + test/CodeGen/AArch64/arm64-platform-reg.ll | 15 +- test/CodeGen/AArch64/arm64-popcnt.ll | 20 +- test/CodeGen/AArch64/arm64-prefetch.ll | 8 +- test/CodeGen/AArch64/arm64-promote-const.ll | 118 +- test/CodeGen/AArch64/arm64-st1.ll | 192 + test/CodeGen/AArch64/arm64-stackmap-nops.ll | 15 + test/CodeGen/AArch64/arm64-stackpointer.ll | 2 +- test/CodeGen/AArch64/arm64-tls-dynamics.ll | 8 +- .../AArch64/arm64-triv-disjoint-mem-access.ll | 14 +- test/CodeGen/AArch64/arm64-variadic-aapcs.ll | 16 +- test/CodeGen/AArch64/arm64-vshuffle.ll | 26 +- test/CodeGen/AArch64/bitcast-v2i8.ll | 15 + test/CodeGen/AArch64/br-to-eh-lpad.ll | 78 + test/CodeGen/AArch64/combine-comparisons-by-cse.ll | 1 - test/CodeGen/AArch64/compiler-ident.ll | 2 +- test/CodeGen/AArch64/cpus.ll | 1 + test/CodeGen/AArch64/dp-3source.ll | 15 + test/CodeGen/AArch64/f16-convert.ll | 15 +- .../CodeGen/AArch64/fast-isel-branch-cond-split.ll | 42 + test/CodeGen/AArch64/fast-isel-branch_weights.ll | 2 +- test/CodeGen/AArch64/fast-isel-memcpy.ll | 15 + test/CodeGen/AArch64/fast-isel-tbz.ll | 162 +- test/CodeGen/AArch64/fdiv-combine.ll | 94 + test/CodeGen/AArch64/fp16-v8-instructions.ll | 8 +- test/CodeGen/AArch64/fpimm.ll | 23 +- test/CodeGen/AArch64/func-argpassing.ll | 10 +- test/CodeGen/AArch64/func-calls.ll | 12 +- test/CodeGen/AArch64/ghc-cc.ll | 89 + test/CodeGen/AArch64/global-merge-1.ll | 1 + test/CodeGen/AArch64/global-merge-2.ll | 1 + test/CodeGen/AArch64/implicit-sret.ll | 13 + test/CodeGen/AArch64/large_shift.ll | 21 + .../AArch64/machine_cse_impdef_killflags.ll | 26 + test/CodeGen/AArch64/neon-scalar-copy.ll | 126 +- test/CodeGen/AArch64/or-combine.ll | 44 + test/CodeGen/AArch64/ragreedy-csr.ll | 48 +- test/CodeGen/AArch64/remat.ll | 1 + test/CodeGen/AArch64/setcc-type-mismatch.ll | 11 + test/CodeGen/ARM/2007-05-09-tailmerge-2.ll | 9 +- test/CodeGen/ARM/2007-05-22-tailmerge-3.ll | 23 +- test/CodeGen/ARM/2009-10-16-Scope.ll | 22 +- test/CodeGen/ARM/2010-04-15-ScavengerDebugValue.ll | 34 +- .../ARM/2010-06-25-Thumb2ITInvalidIterator.ll | 62 +- test/CodeGen/ARM/2010-08-04-StackVariable.ll | 110 +- test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll | 120 +- test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll | 2 +- .../ARM/2011-05-04-MultipleLandingPadSuccs.ll | 10 +- test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll | 114 +- test/CodeGen/ARM/2012-04-24-SplitEHCriticalEdge.ll | 8 +- test/CodeGen/ARM/2012-08-04-DtripleSpillReload.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll | 2 +- test/CodeGen/ARM/2014-08-04-muls-it.ll | 4 +- test/CodeGen/ARM/2015-01-21-thumbv4t-ldstr-opt.ll | 48 + test/CodeGen/ARM/Windows/read-only-data.ll | 2 +- .../CodeGen/ARM/Windows/stack-probe-non-default.ll | 27 + test/CodeGen/ARM/Windows/structors.ll | 2 +- test/CodeGen/ARM/aggregate-padding.ll | 101 + test/CodeGen/ARM/alloc-no-stack-realign.ll | 78 +- test/CodeGen/ARM/arm-abi-attr.ll | 10 +- test/CodeGen/ARM/atomic-64bit.ll | 2 +- test/CodeGen/ARM/atomic-ops-v8.ll | 2 +- test/CodeGen/ARM/big-endian-neon-extend.ll | 81 +- test/CodeGen/ARM/build-attributes-encoding.s | 2 +- test/CodeGen/ARM/build-attributes.ll | 702 +- test/CodeGen/ARM/coalesce-dbgvalue.ll | 64 +- test/CodeGen/ARM/coalesce-subregs.ll | 1 - test/CodeGen/ARM/crc32.ll | 58 + test/CodeGen/ARM/cse-ldrlit.ll | 4 +- test/CodeGen/ARM/cse-libcalls.ll | 6 +- test/CodeGen/ARM/dagcombine-concatvector.ll | 2 +- test/CodeGen/ARM/debug-frame-vararg.ll | 82 +- test/CodeGen/ARM/debug-frame.ll | 70 +- test/CodeGen/ARM/debug-info-arg.ll | 80 +- test/CodeGen/ARM/debug-info-blocks.ll | 346 +- test/CodeGen/ARM/debug-info-branch-folding.ll | 118 +- test/CodeGen/ARM/debug-info-d16-reg.ll | 122 +- test/CodeGen/ARM/debug-info-qreg.ll | 122 +- test/CodeGen/ARM/debug-info-s16-reg.ll | 135 +- test/CodeGen/ARM/debug-info-sreg2.ll | 44 +- test/CodeGen/ARM/debug-segmented-stacks.ll | 68 +- test/CodeGen/ARM/dyn-stackalloc.ll | 14 +- test/CodeGen/ARM/emit-big-cst.ll | 2 +- test/CodeGen/ARM/fold-stack-adjust.ll | 2 +- test/CodeGen/ARM/frame-register.ll | 6 +- test/CodeGen/ARM/ghc-tcreturn-lowered.ll | 21 + test/CodeGen/ARM/global-merge-1.ll | 10 +- test/CodeGen/ARM/globals.ll | 1 + test/CodeGen/ARM/ifcvt-branch-weight-bug.ll | 4 +- test/CodeGen/ARM/ifcvt-branch-weight.ll | 4 +- test/CodeGen/ARM/inline-diagnostics.ll | 2 +- test/CodeGen/ARM/interrupt-attr.ll | 14 +- test/CodeGen/ARM/isel-v8i32-crash.ll | 26 + test/CodeGen/ARM/krait-cpu-div-attribute.ll | 36 + test/CodeGen/ARM/longMAC.ll | 41 + test/CodeGen/ARM/memcpy-inline.ll | 15 +- test/CodeGen/ARM/metadata-default.ll | 4 +- test/CodeGen/ARM/metadata-short-enums.ll | 4 +- test/CodeGen/ARM/metadata-short-wchar.ll | 4 +- test/CodeGen/ARM/named-reg-alloc.ll | 2 +- test/CodeGen/ARM/named-reg-notareg.ll | 2 +- test/CodeGen/ARM/none-macho-v4t.ll | 8 +- test/CodeGen/ARM/null-streamer.ll | 2 + test/CodeGen/ARM/odr_comdat.ll | 16 - test/CodeGen/ARM/out-of-registers.ll | 4 +- test/CodeGen/ARM/section-name.ll | 2 +- test/CodeGen/ARM/setcc-type-mismatch.ll | 11 + test/CodeGen/ARM/sjlj-prepare-critical-edge.ll | 128 +- test/CodeGen/ARM/spill-q.ll | 2 +- test/CodeGen/ARM/stack-alignment.ll | 164 + test/CodeGen/ARM/stack_guard_remat.ll | 2 +- test/CodeGen/ARM/stackpointer.ll | 2 +- test/CodeGen/ARM/sub-cmp-peephole.ll | 60 + test/CodeGen/ARM/tail-call-weak.ll | 19 + test/CodeGen/ARM/tail-call.ll | 5 +- test/CodeGen/ARM/tail-merge-branch-weight.ll | 6 +- test/CodeGen/ARM/taildup-branch-weight.ll | 4 +- test/CodeGen/ARM/thumb1-varalloc.ll | 32 +- test/CodeGen/ARM/thumb1_return_sequence.ll | 48 +- test/CodeGen/ARM/thumb_indirect_calls.ll | 40 + test/CodeGen/ARM/tls1.ll | 14 +- test/CodeGen/ARM/vdup.ll | 6 +- test/CodeGen/ARM/vector-DAGCombine.ll | 8 + test/CodeGen/ARM/vector-load.ll | 253 + test/CodeGen/ARM/vector-store.ll | 258 + test/CodeGen/ARM/vfp-regs-dwarf.ll | 20 +- test/CodeGen/ARM/vld1.ll | 9 + test/CodeGen/ARM/vst1.ll | 10 + test/CodeGen/BPF/alu8.ll | 46 + test/CodeGen/BPF/atomics.ll | 20 + test/CodeGen/BPF/basictest.ll | 28 + test/CodeGen/BPF/byval.ll | 27 + test/CodeGen/BPF/cc_args.ll | 96 + test/CodeGen/BPF/cc_ret.ll | 48 + test/CodeGen/BPF/cmp.ll | 119 + test/CodeGen/BPF/ex1.ll | 46 + test/CodeGen/BPF/intrinsics.ll | 50 + test/CodeGen/BPF/lit.local.cfg | 2 + test/CodeGen/BPF/load.ll | 43 + test/CodeGen/BPF/loops.ll | 111 + test/CodeGen/BPF/many_args1.ll | 12 + test/CodeGen/BPF/many_args2.ll | 15 + test/CodeGen/BPF/sanity.ll | 117 + test/CodeGen/BPF/setcc.ll | 99 + test/CodeGen/BPF/shifts.ll | 101 + test/CodeGen/BPF/sockex2.ll | 326 + test/CodeGen/BPF/struct_ret1.ll | 17 + test/CodeGen/BPF/struct_ret2.ll | 12 + test/CodeGen/BPF/vararg1.ll | 9 + test/CodeGen/Generic/MachineBranchProb.ll | 2 +- test/CodeGen/Generic/dbg_value.ll | 4 +- test/CodeGen/Generic/empty-phi.ll | 19 + test/CodeGen/Generic/overloaded-intrinsic-name.ll | 57 + test/CodeGen/Generic/print-machineinstrs.ll | 2 +- test/CodeGen/Hexagon/BranchPredict.ll | 4 +- test/CodeGen/Hexagon/always-ext.ll | 3 +- test/CodeGen/Hexagon/block-addr.ll | 2 +- test/CodeGen/Hexagon/cext-check.ll | 8 +- test/CodeGen/Hexagon/cmp-not.ll | 50 - test/CodeGen/Hexagon/cmp-to-predreg.ll | 4 +- test/CodeGen/Hexagon/dadd.ll | 2 +- test/CodeGen/Hexagon/dmul.ll | 2 +- test/CodeGen/Hexagon/dsub.ll | 2 +- test/CodeGen/Hexagon/dualstore.ll | 17 +- test/CodeGen/Hexagon/hwloop-dbg.ll | 60 +- test/CodeGen/Hexagon/idxload-with-zero-offset.ll | 40 +- test/CodeGen/Hexagon/intrinsics/alu32_alu.ll | 202 + test/CodeGen/Hexagon/intrinsics/alu32_perm.ll | 104 + test/CodeGen/Hexagon/intrinsics/cr.ll | 132 + test/CodeGen/Hexagon/intrinsics/xtype_alu.ll | 1020 + test/CodeGen/Hexagon/intrinsics/xtype_bit.ll | 329 + test/CodeGen/Hexagon/intrinsics/xtype_complex.ll | 349 + test/CodeGen/Hexagon/intrinsics/xtype_fp.ll | 388 + test/CodeGen/Hexagon/intrinsics/xtype_mpy.ll | 1525 ++ test/CodeGen/Hexagon/intrinsics/xtype_perm.ll | 252 + test/CodeGen/Hexagon/intrinsics/xtype_pred.ll | 351 + test/CodeGen/Hexagon/intrinsics/xtype_shift.ll | 723 + test/CodeGen/Hexagon/newvaluestore.ll | 2 +- test/CodeGen/Hexagon/pred-absolute-store.ll | 2 +- test/CodeGen/Hexagon/struct_args_large.ll | 2 +- test/CodeGen/Inputs/DbgValueOtherTargets.ll | 30 +- test/CodeGen/Mips/2008-08-01-AsmInline.ll | 2 +- test/CodeGen/Mips/2009-11-16-CstPoolLoad.ll | 8 +- test/CodeGen/Mips/Fast-ISel/callabi.ll | 2 +- test/CodeGen/Mips/Fast-ISel/overflt.ll | 64 + test/CodeGen/Mips/Fast-ISel/retabi.ll | 80 + test/CodeGen/Mips/abiflags32.ll | 2 +- test/CodeGen/Mips/atomic.ll | 53 +- test/CodeGen/Mips/blockaddr.ll | 8 +- test/CodeGen/Mips/brsize3.ll | 2 +- test/CodeGen/Mips/brsize3a.ll | 2 +- test/CodeGen/Mips/cconv/arguments-float.ll | 12 +- test/CodeGen/Mips/cconv/arguments-fp128.ll | 8 +- .../Mips/cconv/arguments-hard-float-varargs.ll | 12 +- test/CodeGen/Mips/cconv/arguments-hard-float.ll | 12 +- test/CodeGen/Mips/cconv/arguments-hard-fp128.ll | 8 +- test/CodeGen/Mips/cconv/arguments-struct.ll | 41 + .../cconv/arguments-varargs-small-structs-byte.ll | 282 + ...arguments-varargs-small-structs-combinations.ll | 149 + ...rguments-varargs-small-structs-multiple-args.ll | 161 + test/CodeGen/Mips/cconv/arguments-varargs.ll | 12 +- test/CodeGen/Mips/cconv/arguments.ll | 12 +- test/CodeGen/Mips/cconv/callee-saved-float.ll | 24 +- test/CodeGen/Mips/cconv/callee-saved.ll | 24 +- test/CodeGen/Mips/cconv/memory-layout.ll | 12 +- test/CodeGen/Mips/cconv/reserved-space.ll | 12 +- test/CodeGen/Mips/cconv/return-float.ll | 12 +- test/CodeGen/Mips/cconv/return-hard-float.ll | 12 +- test/CodeGen/Mips/cconv/return-hard-fp128.ll | 8 +- test/CodeGen/Mips/cconv/return-hard-struct-f128.ll | 8 +- test/CodeGen/Mips/cconv/return-struct.ll | 12 +- test/CodeGen/Mips/cconv/return.ll | 12 +- test/CodeGen/Mips/cconv/stack-alignment.ll | 12 +- test/CodeGen/Mips/ci2.ll | 2 +- test/CodeGen/Mips/const1.ll | 2 +- test/CodeGen/Mips/const4a.ll | 2 +- test/CodeGen/Mips/const6.ll | 2 +- test/CodeGen/Mips/const6a.ll | 2 +- test/CodeGen/Mips/fcmp.ll | 90 + test/CodeGen/Mips/fcopysign-f32-f64.ll | 6 +- test/CodeGen/Mips/fcopysign.ll | 6 +- test/CodeGen/Mips/fmadd1.ll | 76 +- test/CodeGen/Mips/fp-indexed-ls.ll | 8 +- test/CodeGen/Mips/fptr2.ll | 20 - test/CodeGen/Mips/fpxx.ll | 8 +- test/CodeGen/Mips/global-address.ll | 8 +- .../CodeGen/Mips/inlineasm-assembler-directives.ll | 23 + test/CodeGen/Mips/inlineasm-cnstrnt-reg.ll | 6 +- test/CodeGen/Mips/inlineasm-cnstrnt-reg64.ll | 2 +- test/CodeGen/Mips/inlineasm64.ll | 2 +- test/CodeGen/Mips/inlineasmmemop.ll | 35 +- test/CodeGen/Mips/largeimmprinting.ll | 4 +- test/CodeGen/Mips/lcb2.ll | 22 +- test/CodeGen/Mips/lcb3c.ll | 4 +- test/CodeGen/Mips/lcb4a.ll | 16 +- test/CodeGen/Mips/lcb5.ll | 36 +- test/CodeGen/Mips/llvm-ir/add.ll | 123 + test/CodeGen/Mips/llvm-ir/and.ll | 99 + test/CodeGen/Mips/llvm-ir/ashr.ll | 200 + test/CodeGen/Mips/llvm-ir/call.ll | 4 + test/CodeGen/Mips/llvm-ir/indirectbr.ll | 4 + test/CodeGen/Mips/llvm-ir/lshr.ll | 188 + test/CodeGen/Mips/llvm-ir/mul.ll | 109 +- test/CodeGen/Mips/llvm-ir/or.ll | 99 + test/CodeGen/Mips/llvm-ir/ret.ll | 4 + test/CodeGen/Mips/llvm-ir/sdiv.ll | 144 + test/CodeGen/Mips/llvm-ir/select.ll | 712 + test/CodeGen/Mips/llvm-ir/shl.ll | 200 + test/CodeGen/Mips/llvm-ir/srem.ll | 139 + test/CodeGen/Mips/llvm-ir/sub.ll | 122 + test/CodeGen/Mips/llvm-ir/udiv.ll | 116 + test/CodeGen/Mips/llvm-ir/urem.ll | 155 + test/CodeGen/Mips/llvm-ir/xor.ll | 99 + test/CodeGen/Mips/load-store-left-right.ll | 16 +- test/CodeGen/Mips/longbranch.ll | 11 +- test/CodeGen/Mips/mbrsize4a.ll | 2 +- test/CodeGen/Mips/micromips-and16.ll | 18 + test/CodeGen/Mips/micromips-atomic.ll | 2 +- test/CodeGen/Mips/micromips-atomic1.ll | 29 + test/CodeGen/Mips/micromips-compact-branches.ll | 19 + test/CodeGen/Mips/micromips-compact-jump.ll | 11 + test/CodeGen/Mips/micromips-delay-slot-jr.ll | 46 + test/CodeGen/Mips/micromips-delay-slot.ll | 14 +- test/CodeGen/Mips/micromips-li.ll | 18 + test/CodeGen/Mips/micromips-or16.ll | 18 + test/CodeGen/Mips/micromips-sw-lw-16.ll | 27 + test/CodeGen/Mips/micromips-xor16.ll | 18 + test/CodeGen/Mips/mips64-sret.ll | 2 +- test/CodeGen/Mips/mips64directive.ll | 4 +- test/CodeGen/Mips/mips64ext.ll | 4 +- test/CodeGen/Mips/mips64extins.ll | 2 +- test/CodeGen/Mips/mips64fpimm0.ll | 4 +- test/CodeGen/Mips/mips64fpldst.ll | 8 +- test/CodeGen/Mips/mips64intldst.ll | 8 +- test/CodeGen/Mips/mips64sinttofpsf.ll | 15 + test/CodeGen/Mips/named-register-n32.ll | 18 + test/CodeGen/Mips/named-register-n64.ll | 17 + test/CodeGen/Mips/named-register-o32.ll | 17 + test/CodeGen/Mips/no-odd-spreg-msa.ll | 131 + test/CodeGen/Mips/octeon.ll | 152 +- test/CodeGen/Mips/powif64_16.ll | 8 +- test/CodeGen/Mips/remat-immed-load.ll | 4 +- test/CodeGen/Mips/start-asm-file.ll | 16 +- test/CodeGen/NVPTX/annotations.ll | 29 +- test/CodeGen/NVPTX/bug21465.ll | 2 +- test/CodeGen/NVPTX/bug22246.ll | 14 + test/CodeGen/NVPTX/bug22322.ll | 62 + test/CodeGen/NVPTX/call-with-alloca-buffer.ll | 2 +- test/CodeGen/NVPTX/calling-conv.ll | 2 +- test/CodeGen/NVPTX/fma-assoc.ll | 25 + test/CodeGen/NVPTX/fma.ll | 25 + test/CodeGen/NVPTX/generic-to-nvvm.ll | 2 +- test/CodeGen/NVPTX/i1-global.ll | 2 +- test/CodeGen/NVPTX/i1-param.ll | 2 +- test/CodeGen/NVPTX/managed.ll | 2 +- test/CodeGen/NVPTX/noduplicate-syncthreads.ll | 4 +- test/CodeGen/NVPTX/nounroll.ll | 37 + test/CodeGen/NVPTX/nvcl-param-align.ll | 16 + test/CodeGen/NVPTX/refl1.ll | 2 +- test/CodeGen/NVPTX/simple-call.ll | 2 +- test/CodeGen/NVPTX/surf-read-cuda.ll | 6 +- test/CodeGen/NVPTX/surf-read.ll | 4 +- test/CodeGen/NVPTX/surf-write-cuda.ll | 6 +- test/CodeGen/NVPTX/surf-write.ll | 4 +- test/CodeGen/NVPTX/tex-read-cuda.ll | 6 +- test/CodeGen/NVPTX/tex-read.ll | 6 +- test/CodeGen/NVPTX/texsurf-queries.ll | 4 +- test/CodeGen/NVPTX/vector-global.ll | 9 + test/CodeGen/NVPTX/weak-linkage.ll | 8 +- test/CodeGen/PowerPC/2007-03-24-cntlzd.ll | 10 +- test/CodeGen/PowerPC/2011-12-05-NoSpillDupCR.ll | 2 +- .../PowerPC/2011-12-06-SpillAndRestoreCR.ll | 2 +- test/CodeGen/PowerPC/Frames-large.ll | 9 +- test/CodeGen/PowerPC/aa-tbaa.ll | 6 +- test/CodeGen/PowerPC/add-fi.ll | 24 + test/CodeGen/PowerPC/addi-licm.ll | 64 + test/CodeGen/PowerPC/arr-fp-arg-no-copy.ll | 23 + test/CodeGen/PowerPC/asm-Zy.ll | 2 +- test/CodeGen/PowerPC/asm-constraints.ll | 13 +- test/CodeGen/PowerPC/bperm.ll | 279 + test/CodeGen/PowerPC/cc.ll | 2 +- test/CodeGen/PowerPC/cmpb-ppc32.ll | 50 + test/CodeGen/PowerPC/cmpb.ll | 204 + test/CodeGen/PowerPC/code-align.ll | 110 + test/CodeGen/PowerPC/constants-i64.ll | 84 + test/CodeGen/PowerPC/crsave.ll | 4 +- test/CodeGen/PowerPC/ctrloops.ll | 25 +- test/CodeGen/PowerPC/dbg.ll | 44 +- test/CodeGen/PowerPC/early-ret2.ll | 2 +- test/CodeGen/PowerPC/fast-isel-const.ll | 27 + test/CodeGen/PowerPC/fdiv-combine.ll | 39 + test/CodeGen/PowerPC/flt-preinc.ll | 40 + test/CodeGen/PowerPC/fma-assoc.ll | 79 + test/CodeGen/PowerPC/fma-ext.ll | 93 + test/CodeGen/PowerPC/fp-to-int-ext.ll | 69 + test/CodeGen/PowerPC/fp-to-int-to-fp.ll | 70 + test/CodeGen/PowerPC/glob-comp-aa-crash.ll | 14 +- test/CodeGen/PowerPC/i1-ext-fold.ll | 54 + test/CodeGen/PowerPC/ia-mem-r0.ll | 94 + test/CodeGen/PowerPC/ia-neg-const.ll | 25 + test/CodeGen/PowerPC/in-asm-f64-reg.ll | 2 +- test/CodeGen/PowerPC/inlineasm-i64-reg.ll | 2 +- test/CodeGen/PowerPC/lbz-from-ld-shift.ll | 18 + test/CodeGen/PowerPC/ld-st-upd.ll | 19 + test/CodeGen/PowerPC/ldtoc-inv.ll | 39 + test/CodeGen/PowerPC/loop-data-prefetch.ll | 29 + test/CodeGen/PowerPC/mult-alt-generic-powerpc.ll | 2 +- test/CodeGen/PowerPC/mult-alt-generic-powerpc64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r0.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r1.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r13.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll | 11 +- test/CodeGen/PowerPC/named-reg-alloc-r2.ll | 8 +- test/CodeGen/PowerPC/no-extra-fp-conv-ldst.ll | 96 + test/CodeGen/PowerPC/no-pref-jumps.ll | 36 + test/CodeGen/PowerPC/p8-isel-sched.ll | 33 + test/CodeGen/PowerPC/post-ra-ec.ll | 47 + test/CodeGen/PowerPC/ppc32-cyclecounter.ll | 20 + test/CodeGen/PowerPC/ppc32-lshrti3.ll | 2 +- test/CodeGen/PowerPC/ppc32-pic-large.ll | 12 +- test/CodeGen/PowerPC/ppc32-pic.ll | 16 +- test/CodeGen/PowerPC/ppc64-anyregcc-crash.ll | 19 + test/CodeGen/PowerPC/ppc64-anyregcc.ll | 367 + test/CodeGen/PowerPC/ppc64-calls.ll | 19 +- test/CodeGen/PowerPC/ppc64-elf-abi.ll | 8 +- test/CodeGen/PowerPC/ppc64-fastcc-fast-isel.ll | 56 + test/CodeGen/PowerPC/ppc64-fastcc.ll | 540 + test/CodeGen/PowerPC/ppc64-func-desc-hoist.ll | 47 + test/CodeGen/PowerPC/ppc64-gep-opt.ll | 157 + test/CodeGen/PowerPC/ppc64-icbt-pwr7.ll | 19 + test/CodeGen/PowerPC/ppc64-icbt-pwr8.ll | 16 + test/CodeGen/PowerPC/ppc64-nonfunc-calls.ll | 69 + test/CodeGen/PowerPC/ppc64-patchpoint.ll | 97 + test/CodeGen/PowerPC/ppc64-r2-alloc.ll | 81 + test/CodeGen/PowerPC/ppc64-stackmap-nops.ll | 24 + test/CodeGen/PowerPC/ppc64-stackmap.ll | 289 + test/CodeGen/PowerPC/ppc64-vaarg-int.ll | 2 +- test/CodeGen/PowerPC/ppc64le-aggregates.ll | 49 +- test/CodeGen/PowerPC/ppc64le-calls.ll | 4 + test/CodeGen/PowerPC/ppc64le-localentry.ll | 5 + test/CodeGen/PowerPC/ppcf128-endian.ll | 2 +- test/CodeGen/PowerPC/pr17168.ll | 932 +- test/CodeGen/PowerPC/preincprep-invoke.ll | 50 + test/CodeGen/PowerPC/qpx-bv-sint.ll | 33 + test/CodeGen/PowerPC/qpx-bv.ll | 37 + test/CodeGen/PowerPC/qpx-func-clobber.ll | 22 + test/CodeGen/PowerPC/qpx-load.ll | 26 + test/CodeGen/PowerPC/qpx-recipest.ll | 194 + test/CodeGen/PowerPC/qpx-rounding-ops.ll | 109 + test/CodeGen/PowerPC/qpx-s-load.ll | 26 + test/CodeGen/PowerPC/qpx-s-sel.ll | 144 + test/CodeGen/PowerPC/qpx-s-store.ll | 25 + test/CodeGen/PowerPC/qpx-sel.ll | 152 + test/CodeGen/PowerPC/qpx-store.ll | 25 + test/CodeGen/PowerPC/qpx-unalperm.ll | 64 + test/CodeGen/PowerPC/retaddr2.ll | 24 + test/CodeGen/PowerPC/rlwimi-and.ll | 6 +- test/CodeGen/PowerPC/rlwimi2.ll | 4 +- test/CodeGen/PowerPC/rm-zext.ll | 89 + test/CodeGen/PowerPC/sdiv-pow2.ll | 67 + test/CodeGen/PowerPC/stack-realign.ll | 8 + test/CodeGen/PowerPC/subreg-postra-2.ll | 175 + test/CodeGen/PowerPC/subreg-postra.ll | 168 + test/CodeGen/PowerPC/tls-cse.ll | 52 + test/CodeGen/PowerPC/tls-pic.ll | 16 +- test/CodeGen/PowerPC/tls-store2.ll | 11 +- test/CodeGen/PowerPC/toc-load-sched-bug.ll | 96 +- test/CodeGen/PowerPC/unwind-dw2-g.ll | 24 +- test/CodeGen/PowerPC/vec-abi-align.ll | 32 +- test/CodeGen/PowerPC/vec_clz.ll | 40 + test/CodeGen/PowerPC/vec_misaligned.ll | 2 +- test/CodeGen/PowerPC/vec_popcnt.ll | 72 + test/CodeGen/PowerPC/vec_shuffle_le.ll | 2 +- test/CodeGen/PowerPC/vec_veqv_vnand_vorc.ll | 29 + test/CodeGen/PowerPC/vsel-prom.ll | 23 + test/CodeGen/PowerPC/vsx-args.ll | 1 + test/CodeGen/PowerPC/vsx-fma-m.ll | 112 +- test/CodeGen/PowerPC/vsx-infl-copy1.ll | 133 + test/CodeGen/PowerPC/vsx-infl-copy2.ll | 114 + test/CodeGen/PowerPC/vsx-ldst-builtin-le.ll | 172 + test/CodeGen/PowerPC/vsx-ldst.ll | 10 + test/CodeGen/PowerPC/vsx-p8.ll | 25 +- test/CodeGen/PowerPC/vsx-self-copy.ll | 1 + test/CodeGen/PowerPC/vsx-spill-norwstore.ll | 63 + test/CodeGen/PowerPC/vsx-spill.ll | 31 +- test/CodeGen/PowerPC/vsx.ll | 501 +- test/CodeGen/PowerPC/vsx_insert_extract_le.ll | 52 + test/CodeGen/PowerPC/vsx_shuffle_le.ll | 207 + test/CodeGen/PowerPC/xxleqv_xxlnand_xxlorc.ll | 52 + test/CodeGen/PowerPC/zext-free.ll | 37 + test/CodeGen/R600/128bit-kernel-args.ll | 33 +- test/CodeGen/R600/32-bit-local-address-space.ll | 5 +- test/CodeGen/R600/64bit-kernel-args.ll | 13 +- test/CodeGen/R600/add-debug.ll | 3 +- test/CodeGen/R600/add.ll | 143 +- test/CodeGen/R600/add_i64.ll | 2 +- test/CodeGen/R600/address-space.ll | 6 +- test/CodeGen/R600/and.ll | 154 +- test/CodeGen/R600/anyext.ll | 3 +- test/CodeGen/R600/array-ptr-calc-i32.ll | 4 +- test/CodeGen/R600/array-ptr-calc-i64.ll | 2 +- test/CodeGen/R600/atomic_cmp_swap_local.ll | 85 +- test/CodeGen/R600/atomic_load_add.ll | 3 +- test/CodeGen/R600/atomic_load_sub.ll | 3 +- test/CodeGen/R600/basic-branch.ll | 3 +- test/CodeGen/R600/basic-loop.ll | 4 +- test/CodeGen/R600/bfi_int.ll | 31 +- test/CodeGen/R600/bitcast.ll | 3 +- test/CodeGen/R600/bswap.ll | 3 +- test/CodeGen/R600/build_vector.ll | 45 +- test/CodeGen/R600/call.ll | 3 +- test/CodeGen/R600/call_fs.ll | 16 +- test/CodeGen/R600/cf_end.ll | 10 +- test/CodeGen/R600/codegen-prepare-addrmode-sext.ll | 2 +- test/CodeGen/R600/commute_modifiers.ll | 14 +- test/CodeGen/R600/concat_vectors.ll | 3 +- test/CodeGen/R600/copy-illegal-type.ll | 3 +- test/CodeGen/R600/copy-to-reg.ll | 3 +- test/CodeGen/R600/ctlz_zero_undef.ll | 3 +- test/CodeGen/R600/ctpop.ll | 177 +- test/CodeGen/R600/ctpop64.ll | 77 +- test/CodeGen/R600/cttz_zero_undef.ll | 3 +- test/CodeGen/R600/cvt_f32_ubyte.ll | 39 +- test/CodeGen/R600/cvt_flr_i32_f32.ll | 86 + test/CodeGen/R600/cvt_rpi_i32_f32.ll | 83 + test/CodeGen/R600/default-fp-mode.ll | 21 +- .../ds-negative-offset-addressing-mode-loop.ll | 4 +- test/CodeGen/R600/ds_read2.ll | 2 +- test/CodeGen/R600/ds_read2_offset_order.ll | 45 + test/CodeGen/R600/ds_read2st64.ll | 6 +- test/CodeGen/R600/ds_write2.ll | 28 +- test/CodeGen/R600/ds_write2st64.ll | 16 +- test/CodeGen/R600/elf.ll | 26 +- test/CodeGen/R600/elf.r600.ll | 18 +- test/CodeGen/R600/empty-function.ll | 3 +- test/CodeGen/R600/endcf-loop-header.ll | 34 + test/CodeGen/R600/extload-private.ll | 46 + test/CodeGen/R600/extload.ll | 94 +- test/CodeGen/R600/extract_vector_elt_i16.ll | 3 +- test/CodeGen/R600/fabs.f64.ll | 2 +- test/CodeGen/R600/fabs.ll | 35 +- test/CodeGen/R600/fadd.ll | 3 +- test/CodeGen/R600/fadd64.ll | 3 +- test/CodeGen/R600/fceil.ll | 3 +- test/CodeGen/R600/fceil64.ll | 20 +- test/CodeGen/R600/fcmp64.ll | 13 +- test/CodeGen/R600/fconst64.ll | 3 +- test/CodeGen/R600/fcopysign.f32.ll | 21 +- test/CodeGen/R600/fcopysign.f64.ll | 23 +- test/CodeGen/R600/fdiv.f64.ll | 96 + test/CodeGen/R600/fdiv.ll | 3 +- test/CodeGen/R600/fdiv64.ll | 14 - test/CodeGen/R600/ffloor.f64.ll | 106 + test/CodeGen/R600/ffloor.ll | 131 +- test/CodeGen/R600/flat-address-space.ll | 6 +- test/CodeGen/R600/floor.ll | 7 +- test/CodeGen/R600/fma-combine.ll | 368 + test/CodeGen/R600/fma.f64.ll | 3 +- test/CodeGen/R600/fma.ll | 2 +- test/CodeGen/R600/fmax3.ll | 9 +- test/CodeGen/R600/fmax_legacy.f64.ll | 67 + test/CodeGen/R600/fmax_legacy.ll | 51 +- test/CodeGen/R600/fmaxnum.f64.ll | 3 +- test/CodeGen/R600/fmaxnum.ll | 3 +- test/CodeGen/R600/fmin3.ll | 10 +- test/CodeGen/R600/fmin_legacy.f64.ll | 77 + test/CodeGen/R600/fmin_legacy.ll | 51 +- test/CodeGen/R600/fminnum.f64.ll | 3 +- test/CodeGen/R600/fminnum.ll | 3 +- test/CodeGen/R600/fmul.ll | 3 +- test/CodeGen/R600/fmul64.ll | 3 +- test/CodeGen/R600/fmuladd.ll | 18 +- test/CodeGen/R600/fnearbyint.ll | 5 +- test/CodeGen/R600/fneg-fabs.f64.ll | 9 +- test/CodeGen/R600/fneg-fabs.ll | 3 +- test/CodeGen/R600/fneg.f64.ll | 27 +- test/CodeGen/R600/fneg.ll | 24 +- test/CodeGen/R600/fp-classify.ll | 131 + test/CodeGen/R600/fp16_to_fp.ll | 3 +- test/CodeGen/R600/fp32_to_fp16.ll | 3 +- test/CodeGen/R600/fp_to_sint.f64.ll | 4 +- test/CodeGen/R600/fp_to_sint.ll | 18 +- test/CodeGen/R600/fp_to_uint.f64.ll | 4 +- test/CodeGen/R600/fp_to_uint.ll | 32 +- test/CodeGen/R600/fpext.ll | 44 +- test/CodeGen/R600/fptrunc.ll | 44 +- test/CodeGen/R600/frem.ll | 63 +- test/CodeGen/R600/fsqrt.ll | 7 +- test/CodeGen/R600/fsub.ll | 3 +- test/CodeGen/R600/fsub64.ll | 107 +- test/CodeGen/R600/ftrunc.f64.ll | 9 +- test/CodeGen/R600/ftrunc.ll | 3 +- test/CodeGen/R600/gep-address-space.ll | 5 +- test/CodeGen/R600/global-directive.ll | 3 +- test/CodeGen/R600/global-extload-i1.ll | 302 + test/CodeGen/R600/global-extload-i16.ll | 302 + test/CodeGen/R600/global-extload-i32.ll | 457 + test/CodeGen/R600/global-extload-i8.ll | 299 + test/CodeGen/R600/global-zero-initializer.ll | 3 +- test/CodeGen/R600/global_atomics.ll | 82 +- test/CodeGen/R600/gv-const-addrspace-fail.ll | 2 +- test/CodeGen/R600/gv-const-addrspace.ll | 8 +- test/CodeGen/R600/half.ll | 3 +- test/CodeGen/R600/hsa.ll | 14 + test/CodeGen/R600/i1-copy-implicit-def.ll | 3 +- test/CodeGen/R600/i1-copy-phi.ll | 3 +- test/CodeGen/R600/icmp64.ll | 3 +- test/CodeGen/R600/imm.ll | 488 +- test/CodeGen/R600/indirect-addressing-si.ll | 3 +- test/CodeGen/R600/indirect-private-64.ll | 6 +- test/CodeGen/R600/infinite-loop.ll | 3 +- test/CodeGen/R600/inline-asm.ll | 12 + test/CodeGen/R600/inline-calls.ll | 3 +- test/CodeGen/R600/input-mods.ll | 18 +- test/CodeGen/R600/insert_subreg.ll | 3 +- test/CodeGen/R600/insert_vector_elt.ll | 3 +- test/CodeGen/R600/kernel-args.ll | 540 +- test/CodeGen/R600/large-alloca.ll | 3 +- test/CodeGen/R600/large-constant-initializer.ll | 3 +- test/CodeGen/R600/lds-initializer.ll | 3 +- test/CodeGen/R600/lds-zero-initializer.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.abs.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.barrier.global.ll | 4 +- test/CodeGen/R600/llvm.AMDGPU.barrier.local.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.bfe.i32.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.bfe.u32.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.bfi.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.bfm.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.brev.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.clamp.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.class.ll | 497 + test/CodeGen/R600/llvm.AMDGPU.cvt_f32_ubyte.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.div_fixup.ll | 22 +- test/CodeGen/R600/llvm.AMDGPU.div_fmas.ll | 166 +- test/CodeGen/R600/llvm.AMDGPU.div_scale.ll | 87 +- test/CodeGen/R600/llvm.AMDGPU.fract.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.imad24.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.imax.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.imin.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.imul24.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.kill.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.ldexp.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.legacy.rsq.ll | 2 +- test/CodeGen/R600/llvm.AMDGPU.rcp.f64.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.rcp.ll | 9 +- test/CodeGen/R600/llvm.AMDGPU.rsq.clamped.f64.ll | 14 +- test/CodeGen/R600/llvm.AMDGPU.rsq.clamped.ll | 11 +- test/CodeGen/R600/llvm.AMDGPU.rsq.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.trig_preop.ll | 3 +- test/CodeGen/R600/llvm.AMDGPU.trunc.ll | 13 +- test/CodeGen/R600/llvm.AMDGPU.umad24.ll | 4 +- test/CodeGen/R600/llvm.AMDGPU.umax.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.umin.ll | 5 +- test/CodeGen/R600/llvm.AMDGPU.umul24.ll | 3 +- test/CodeGen/R600/llvm.SI.fs.interp.constant.ll | 21 - test/CodeGen/R600/llvm.SI.fs.interp.ll | 30 + test/CodeGen/R600/llvm.SI.gather4.ll | 3 +- test/CodeGen/R600/llvm.SI.getlod.ll | 3 +- test/CodeGen/R600/llvm.SI.image.ll | 3 +- test/CodeGen/R600/llvm.SI.image.sample.ll | 23 +- test/CodeGen/R600/llvm.SI.image.sample.o.ll | 23 +- test/CodeGen/R600/llvm.SI.imageload.ll | 9 +- test/CodeGen/R600/llvm.SI.load.dword.ll | 53 +- test/CodeGen/R600/llvm.SI.resinfo.ll | 3 +- test/CodeGen/R600/llvm.SI.sample-masked.ll | 3 +- test/CodeGen/R600/llvm.SI.sample.ll | 3 +- test/CodeGen/R600/llvm.SI.sampled.ll | 3 +- test/CodeGen/R600/llvm.SI.sendmsg-m0.ll | 20 + test/CodeGen/R600/llvm.SI.sendmsg.ll | 3 +- test/CodeGen/R600/llvm.SI.tbuffer.store.ll | 3 +- test/CodeGen/R600/llvm.SI.tid.ll | 8 +- test/CodeGen/R600/llvm.amdgpu.kilp.ll | 5 +- test/CodeGen/R600/llvm.amdgpu.lrp.ll | 3 +- test/CodeGen/R600/llvm.cos.ll | 3 +- test/CodeGen/R600/llvm.exp2.ll | 91 +- test/CodeGen/R600/llvm.floor.ll | 54 - test/CodeGen/R600/llvm.log2.ll | 91 +- test/CodeGen/R600/llvm.memcpy.ll | 37 +- test/CodeGen/R600/llvm.rint.f64.ll | 5 +- test/CodeGen/R600/llvm.rint.ll | 3 +- test/CodeGen/R600/llvm.round.f64.ll | 74 + test/CodeGen/R600/llvm.round.ll | 78 +- test/CodeGen/R600/llvm.sin.ll | 6 +- test/CodeGen/R600/llvm.sqrt.ll | 59 +- test/CodeGen/R600/llvm.trunc.ll | 13 - test/CodeGen/R600/load-i1.ll | 74 +- test/CodeGen/R600/load.ll | 597 +- test/CodeGen/R600/load.vec.ll | 21 +- test/CodeGen/R600/load64.ll | 3 +- test/CodeGen/R600/local-64.ll | 53 +- test/CodeGen/R600/local-atomics.ll | 271 +- test/CodeGen/R600/local-atomics64.ll | 237 +- test/CodeGen/R600/local-memory-two-objects.ll | 38 +- test/CodeGen/R600/local-memory.ll | 8 +- test/CodeGen/R600/loop-address.ll | 8 +- test/CodeGen/R600/loop-idiom.ll | 3 +- test/CodeGen/R600/lshl.ll | 3 +- test/CodeGen/R600/lshr.ll | 3 +- test/CodeGen/R600/m0-spill.ll | 3 +- test/CodeGen/R600/mad-combine.ll | 567 + test/CodeGen/R600/mad-sub.ll | 6 +- test/CodeGen/R600/mad_int24.ll | 3 +- test/CodeGen/R600/mad_uint24.ll | 3 +- test/CodeGen/R600/madak.ll | 193 + test/CodeGen/R600/madmk.ll | 181 + test/CodeGen/R600/max.ll | 2 +- test/CodeGen/R600/max3.ll | 2 +- test/CodeGen/R600/min.ll | 23 +- test/CodeGen/R600/min3.ll | 2 +- test/CodeGen/R600/missing-store.ll | 2 +- test/CodeGen/R600/mubuf.ll | 73 +- test/CodeGen/R600/mul.ll | 3 +- test/CodeGen/R600/mul_int24.ll | 3 +- test/CodeGen/R600/mul_uint24.ll | 3 +- test/CodeGen/R600/mulhu.ll | 5 +- .../R600/no-initializer-constant-addrspace.ll | 3 +- test/CodeGen/R600/no-shrink-extloads.ll | 191 + test/CodeGen/R600/operand-folding.ll | 113 + test/CodeGen/R600/operand-spacing.ll | 13 +- test/CodeGen/R600/or.ll | 59 +- test/CodeGen/R600/private-memory-atomics.ll | 3 +- test/CodeGen/R600/private-memory-broken.ll | 3 +- test/CodeGen/R600/private-memory.ll | 12 +- test/CodeGen/R600/r600-encoding.ll | 12 +- test/CodeGen/R600/register-count-comments.ll | 2 +- test/CodeGen/R600/reorder-stores.ll | 3 +- test/CodeGen/R600/rotl.i64.ll | 27 +- test/CodeGen/R600/rotl.ll | 3 +- test/CodeGen/R600/rotr.i64.ll | 27 +- test/CodeGen/R600/rotr.ll | 3 +- test/CodeGen/R600/rsq.ll | 40 +- test/CodeGen/R600/s_movk_i32.ll | 3 +- test/CodeGen/R600/saddo.ll | 3 +- test/CodeGen/R600/salu-to-valu.ll | 2 +- test/CodeGen/R600/scalar_to_vector.ll | 3 +- test/CodeGen/R600/schedule-global-loads.ll | 4 +- test/CodeGen/R600/schedule-kernel-arg-loads.ll | 10 +- .../R600/schedule-vs-if-nested-loop-failure.ll | 3 +- test/CodeGen/R600/scratch-buffer.ll | 87 + test/CodeGen/R600/sdiv.ll | 5 +- test/CodeGen/R600/sdivrem24.ll | 3 +- test/CodeGen/R600/sdivrem64.ll | 225 + test/CodeGen/R600/select-i1.ll | 3 +- test/CodeGen/R600/select-vectors.ll | 3 +- test/CodeGen/R600/select64.ll | 20 +- test/CodeGen/R600/selectcc-opt.ll | 3 +- test/CodeGen/R600/selectcc.ll | 3 +- test/CodeGen/R600/setcc-opt.ll | 237 +- test/CodeGen/R600/setcc.ll | 96 +- test/CodeGen/R600/setcc64.ll | 46 +- test/CodeGen/R600/seto.ll | 3 +- test/CodeGen/R600/setuo.ll | 3 +- test/CodeGen/R600/sext-in-reg.ll | 2 +- test/CodeGen/R600/sgpr-control-flow.ll | 43 +- test/CodeGen/R600/sgpr-copy-duplicate-operand.ll | 3 +- test/CodeGen/R600/sgpr-copy.ll | 11 +- test/CodeGen/R600/shl.ll | 228 +- test/CodeGen/R600/shl_add_constant.ll | 2 +- test/CodeGen/R600/shl_add_ptr.ll | 14 +- test/CodeGen/R600/si-annotate-cf-assertion.ll | 3 +- test/CodeGen/R600/si-lod-bias.ll | 7 +- test/CodeGen/R600/si-sgpr-spill.ll | 6 +- test/CodeGen/R600/si-triv-disjoint-mem-access.ll | 18 +- test/CodeGen/R600/si-vector-hang.ll | 21 +- test/CodeGen/R600/sign_extend.ll | 8 +- .../R600/simplify-demanded-bits-build-pair.ll | 3 +- test/CodeGen/R600/sint_to_fp.f64.ll | 15 +- test/CodeGen/R600/sint_to_fp.ll | 3 +- test/CodeGen/R600/smrd.ll | 58 +- test/CodeGen/R600/split-scalar-i64-add.ll | 2 +- test/CodeGen/R600/sra.ll | 271 +- test/CodeGen/R600/srem.ll | 64 +- test/CodeGen/R600/srl.ll | 279 +- test/CodeGen/R600/ssubo.ll | 3 +- test/CodeGen/R600/store-barrier.ll | 4 +- test/CodeGen/R600/store-v3i32.ll | 3 +- test/CodeGen/R600/store-v3i64.ll | 3 +- test/CodeGen/R600/store-vector-ptrs.ll | 3 +- test/CodeGen/R600/store.ll | 328 +- test/CodeGen/R600/store.r600.ll | 10 +- test/CodeGen/R600/sub.ll | 87 +- test/CodeGen/R600/subreg-coalescer-crash.ll | 109 + test/CodeGen/R600/swizzle-export.ll | 18 +- test/CodeGen/R600/trunc-cmp-constant.ll | 170 + test/CodeGen/R600/trunc-store-i1.ll | 3 +- test/CodeGen/R600/trunc.ll | 35 +- test/CodeGen/R600/tti-unroll-prefs.ll | 58 + test/CodeGen/R600/uaddo.ll | 3 +- test/CodeGen/R600/udiv.ll | 27 +- test/CodeGen/R600/udivrem.ll | 55 +- test/CodeGen/R600/udivrem24.ll | 3 +- test/CodeGen/R600/udivrem64.ll | 149 +- test/CodeGen/R600/uint_to_fp.f64.ll | 111 +- test/CodeGen/R600/uint_to_fp.ll | 36 +- test/CodeGen/R600/unaligned-load-store.ll | 207 +- .../R600/unhandled-loop-condition-assertion.ll | 3 +- test/CodeGen/R600/urecip.ll | 3 +- test/CodeGen/R600/urem.ll | 100 +- test/CodeGen/R600/use-sgpr-multiple-times.ll | 73 +- test/CodeGen/R600/usubo.ll | 5 +- test/CodeGen/R600/v_cndmask.ll | 3 +- test/CodeGen/R600/valu-i1.ll | 153 +- test/CodeGen/R600/vector-alloca.ll | 6 +- test/CodeGen/R600/vertex-fetch-encoding.ll | 16 +- test/CodeGen/R600/vop-shrink.ll | 3 +- test/CodeGen/R600/vselect.ll | 59 +- test/CodeGen/R600/wait.ll | 12 +- test/CodeGen/R600/work-item-intrinsics.ll | 72 +- test/CodeGen/R600/wrong-transalu-pos-fix.ll | 6 +- test/CodeGen/R600/xor.ll | 108 +- test/CodeGen/R600/zero_extend.ll | 31 +- .../SPARC/2008-10-10-InlineAsmMemoryOperand.ll | 2 +- test/CodeGen/SPARC/float.ll | 4 +- test/CodeGen/SPARC/fp128.ll | 32 +- test/CodeGen/SPARC/inlineasm.ll | 2 +- test/CodeGen/SPARC/mult-alt-generic-sparc.ll | 2 +- test/CodeGen/SPARC/setjmp.ll | 10 +- test/CodeGen/SystemZ/alias-01.ll | 6 +- test/CodeGen/SystemZ/and-08.ll | 10 +- test/CodeGen/SystemZ/asm-01.ll | 2 +- test/CodeGen/SystemZ/asm-02.ll | 2 +- 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 | 2 +- test/CodeGen/SystemZ/asm-07.ll | 2 +- test/CodeGen/SystemZ/asm-08.ll | 2 +- test/CodeGen/SystemZ/asm-09.ll | 2 +- test/CodeGen/SystemZ/asm-10.ll | 2 +- test/CodeGen/SystemZ/asm-11.ll | 2 +- test/CodeGen/SystemZ/asm-12.ll | 2 +- test/CodeGen/SystemZ/asm-13.ll | 2 +- test/CodeGen/SystemZ/asm-14.ll | 2 +- test/CodeGen/SystemZ/asm-15.ll | 2 +- test/CodeGen/SystemZ/asm-16.ll | 2 +- test/CodeGen/SystemZ/asm-17.ll | 2 +- test/CodeGen/SystemZ/asm-18.ll | 2 +- test/CodeGen/SystemZ/fp-cmp-04.ll | 2 +- test/CodeGen/SystemZ/int-cmp-44.ll | 2 +- test/CodeGen/SystemZ/int-cmp-45.ll | 2 +- test/CodeGen/SystemZ/memchr-02.ll | 2 +- test/CodeGen/SystemZ/memcpy-02.ll | 10 +- test/CodeGen/SystemZ/tls-01.ll | 6 +- test/CodeGen/SystemZ/tls-02.ll | 18 + test/CodeGen/SystemZ/tls-03.ll | 23 + test/CodeGen/SystemZ/tls-04.ll | 28 + test/CodeGen/SystemZ/tls-05.ll | 15 + test/CodeGen/SystemZ/tls-06.ll | 17 + test/CodeGen/SystemZ/tls-07.ll | 16 + test/CodeGen/Thumb/2010-07-15-debugOrdering.ll | 212 +- test/CodeGen/Thumb/fastcc.ll | 2 +- test/CodeGen/Thumb/iabs.ll | 2 +- test/CodeGen/Thumb/stack-access.ll | 74 + test/CodeGen/Thumb/stm-merge.ll | 9 +- test/CodeGen/Thumb/vargs.ll | 16 +- test/CodeGen/Thumb2/aligned-spill.ll | 8 +- test/CodeGen/Thumb2/constant-islands-jump-table.ll | 47 + .../Thumb2/constant-islands-new-island-padding.ll | 42 + test/CodeGen/Thumb2/ifcvt-neon.ll | 6 +- test/CodeGen/Thumb2/thumb2-cmn.ll | 2 +- test/CodeGen/Thumb2/thumb2-spill-q.ll | 2 +- test/CodeGen/X86/2006-05-22-FPSetEQ.ll | 9 +- test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll | 15 - test/CodeGen/X86/2007-04-25-MMX-PADDQ.ll | 64 - test/CodeGen/X86/2007-06-15-IntToMMX.ll | 19 - test/CodeGen/X86/2008-10-06-MMXISelBug.ll | 12 - test/CodeGen/X86/2009-01-25-NoSSE.ll | 4 +- test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll | 54 +- .../X86/2009-06-05-ScalarToVectorByteMMX.ll | 9 - test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll | 10 - .../X86/2009-06-18-movlp-shuffle-register.ll | 2 +- .../CodeGen/X86/2009-08-02-mmx-scalar-to-vector.ll | 12 - test/CodeGen/X86/2009-10-16-Scope.ll | 22 +- test/CodeGen/X86/2010-01-07-UAMemFeature.ll | 11 - test/CodeGen/X86/2010-01-18-DbgValue.ll | 46 +- test/CodeGen/X86/2010-02-01-DbgValueCrash.ll | 36 +- test/CodeGen/X86/2010-02-11-NonTemporal.ll | 2 +- test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll | 22 +- test/CodeGen/X86/2010-04-23-mmx-movdq2q.ll | 100 - .../X86/2010-05-05-LocalAllocEarlyClobber.ll | 2 +- test/CodeGen/X86/2010-05-25-DotDebugLoc.ll | 142 +- test/CodeGen/X86/2010-05-26-DotDebugLoc.ll | 80 +- test/CodeGen/X86/2010-05-28-Crash.ll | 48 +- test/CodeGen/X86/2010-06-01-DeadArg-DbgInfo.ll | 74 +- .../X86/2010-06-15-FastAllocEarlyCLobber.ll | 2 +- test/CodeGen/X86/2010-06-25-asm-RA-crash.ll | 2 +- .../CodeGen/X86/2010-06-28-FastAllocTiedOperand.ll | 2 +- test/CodeGen/X86/2010-07-06-DbgCrash.ll | 36 +- test/CodeGen/X86/2010-08-04-StackVariable.ll | 110 +- test/CodeGen/X86/2010-09-16-EmptyFilename.ll | 36 +- test/CodeGen/X86/2010-09-16-asmcrash.ll | 2 +- test/CodeGen/X86/2010-11-02-DbgParameter.ll | 42 +- test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll | 78 +- test/CodeGen/X86/2011-06-14-mmx-inlineasm.ll | 4 +- test/CodeGen/X86/2011-10-19-widen_vselect.ll | 2 +- test/CodeGen/X86/2011-11-30-or.ll | 14 +- test/CodeGen/X86/2012-01-16-mfence-nosse-flags.ll | 2 +- test/CodeGen/X86/2012-05-19-avx2-store.ll | 13 - test/CodeGen/X86/2012-07-15-broadcastfold.ll | 1 - test/CodeGen/X86/2012-11-30-handlemove-dbg.ll | 26 +- test/CodeGen/X86/2012-11-30-misched-dbg.ll | 68 +- test/CodeGen/X86/2012-11-30-regpres-dbg.ll | 22 +- .../X86/2013-10-14-FastISel-incorrect-vreg.ll | 6 +- test/CodeGen/X86/MachineBranchProb.ll | 2 +- test/CodeGen/X86/MachineSink-DbgValue.ll | 52 +- test/CodeGen/X86/MergeConsecutiveStores.ll | 133 +- test/CodeGen/X86/StackColoring-dbg.ll | 14 +- test/CodeGen/X86/SwizzleShuff.ll | 15 +- test/CodeGen/X86/asm-label.ll | 6 +- test/CodeGen/X86/atomic16.ll | 24 +- test/CodeGen/X86/avx-cvt.ll | 17 + test/CodeGen/X86/avx-intrinsics-x86-upgrade.ll | 14 + test/CodeGen/X86/avx-intrinsics-x86.ll | 32 - test/CodeGen/X86/avx-splat.ll | 6 +- test/CodeGen/X86/avx-trunc.ll | 6 +- test/CodeGen/X86/avx-vperm2x128.ll | 19 +- test/CodeGen/X86/avx.ll | 2 +- test/CodeGen/X86/avx1-stack-reload-folding.ll | 68 - test/CodeGen/X86/avx2-conversions.ll | 2 +- test/CodeGen/X86/avx2-gather.ll | 27 + test/CodeGen/X86/avx2-intrinsics-x86-upgrade.ll | 31 + test/CodeGen/X86/avx2-intrinsics-x86.ll | 32 - test/CodeGen/X86/avx2-nontemporal.ll | 2 +- test/CodeGen/X86/avx2-pmovxrm-intrinsics.ll | 110 + test/CodeGen/X86/avx2-vbroadcast.ll | 2 +- test/CodeGen/X86/avx512-arith.ll | 190 + test/CodeGen/X86/avx512-fma-intrinsics.ll | 351 + test/CodeGen/X86/avx512-i1test.ll | 45 + test/CodeGen/X86/avx512-insert-extract.ll | 19 +- test/CodeGen/X86/avx512-intel-ocl.ll | 105 + test/CodeGen/X86/avx512-intrinsics.ll | 692 +- test/CodeGen/X86/avx512-logic.ll | 101 + test/CodeGen/X86/avx512-mask-op.ll | 84 +- test/CodeGen/X86/avx512-nontemporal.ll | 2 +- test/CodeGen/X86/avx512-round.ll | 106 + test/CodeGen/X86/avx512-vbroadcast.ll | 120 + test/CodeGen/X86/avx512-vec-cmp.ll | 18 +- test/CodeGen/X86/avx512bw-arith.ll | 102 + test/CodeGen/X86/avx512bw-intrinsics.ll | 186 +- test/CodeGen/X86/avx512bw-vec-cmp.ll | 8 +- test/CodeGen/X86/avx512bwvl-arith.ll | 206 + test/CodeGen/X86/avx512bwvl-intrinsics.ll | 657 +- test/CodeGen/X86/avx512er-intrinsics.ll | 41 +- test/CodeGen/X86/avx512vl-arith.ll | 794 + test/CodeGen/X86/avx512vl-intrinsics.ll | 555 +- test/CodeGen/X86/avx512vl-logic.ll | 137 + test/CodeGen/X86/avx512vl-nontemporal.ll | 2 +- test/CodeGen/X86/avx512vl-vec-cmp.ll | 16 +- test/CodeGen/X86/barrier.ll | 3 +- test/CodeGen/X86/bitcast-mmx.ll | 77 + test/CodeGen/X86/block-placement.ll | 6 +- test/CodeGen/X86/break-avx-dep.ll | 29 - test/CodeGen/X86/break-false-dep.ll | 201 + test/CodeGen/X86/break-sse-dep.ll | 62 - test/CodeGen/X86/bswap-vector.ll | 366 +- test/CodeGen/X86/chain_order.ll | 16 +- test/CodeGen/X86/clobber-fi0.ll | 2 +- test/CodeGen/X86/cmov.ll | 2 +- test/CodeGen/X86/cmpxchg-clobber-flags.ll | 29 +- test/CodeGen/X86/coalesce_commute_subreg.ll | 51 + test/CodeGen/X86/coalescer-dce.ll | 2 +- test/CodeGen/X86/codegen-prepare-extload.ll | 348 +- test/CodeGen/X86/coff-comdat.ll | 50 +- test/CodeGen/X86/coff-comdat2.ll | 2 +- test/CodeGen/X86/coff-comdat3.ll | 2 +- test/CodeGen/X86/combine-and.ll | 148 +- test/CodeGen/X86/combine-or.ll | 46 +- test/CodeGen/X86/commute-clmul.ll | 60 + test/CodeGen/X86/commute-fcmp.ll | 340 + test/CodeGen/X86/commute-xop.ll | 184 + test/CodeGen/X86/compact-unwind.ll | 88 +- test/CodeGen/X86/constant-combines.ll | 35 + test/CodeGen/X86/constant-hoisting-optnone.ll | 21 + test/CodeGen/X86/copysign-constant-magnitude.ll | 105 + test/CodeGen/X86/copysign-zero.ll | 14 - test/CodeGen/X86/cppeh-catch-all.ll | 83 + test/CodeGen/X86/cppeh-catch-scalar.ll | 123 + test/CodeGen/X86/cppeh-frame-vars.ll | 261 + test/CodeGen/X86/cpus.ll | 35 + test/CodeGen/X86/crash-O0.ll | 22 +- test/CodeGen/X86/crash.ll | 4 +- .../X86/dbg-changes-codegen-branch-folding.ll | 214 +- test/CodeGen/X86/dbg-changes-codegen.ll | 14 +- test/CodeGen/X86/dbg-combine.ll | 113 + test/CodeGen/X86/dllexport-x86_64.ll | 7 +- test/CodeGen/X86/dllexport.ll | 12 +- test/CodeGen/X86/dwarf-comp-dir.ll | 14 +- test/CodeGen/X86/dwarf-eh-prepare.ll | 51 + test/CodeGen/X86/elf-comdat.ll | 4 +- test/CodeGen/X86/elf-comdat2.ll | 2 +- test/CodeGen/X86/equiv_with_fndef.ll | 10 + test/CodeGen/X86/equiv_with_vardef.ll | 8 + test/CodeGen/X86/extractelement-load.ll | 14 +- test/CodeGen/X86/f16c-intrinsics.ll | 17 + test/CodeGen/X86/fast-isel-branch_weights.ll | 2 +- test/CodeGen/X86/fast-isel-call-bool.ll | 18 + test/CodeGen/X86/fast-isel-cmp-branch.ll | 2 +- .../X86/fast-isel-double-half-convertion.ll | 23 + .../CodeGen/X86/fast-isel-float-half-convertion.ll | 28 + test/CodeGen/X86/fast-isel-fptrunc-fpext.ll | 65 + test/CodeGen/X86/fast-isel-gep.ll | 2 +- test/CodeGen/X86/fast-isel-int-float-conversion.ll | 45 + test/CodeGen/X86/fastmath-float-half-conversion.ll | 52 + test/CodeGen/X86/float-conv-elim.ll | 32 + test/CodeGen/X86/fold-load-unops.ll | 57 + test/CodeGen/X86/fold-tied-op.ll | 168 +- test/CodeGen/X86/fold-vex.ll | 39 +- test/CodeGen/X86/force-align-stack-alloca.ll | 4 +- test/CodeGen/X86/fp-double-rounding.ll | 31 + test/CodeGen/X86/fpstack-debuginstr-kill.ll | 54 +- test/CodeGen/X86/frameaddr.ll | 28 +- test/CodeGen/X86/frameallocate.ll | 43 + test/CodeGen/X86/gather-addresses.ll | 83 +- test/CodeGen/X86/gcc_except_table.ll | 2 +- test/CodeGen/X86/ghc-cc.ll | 10 +- test/CodeGen/X86/ghc-cc64.ll | 10 +- test/CodeGen/X86/global-sections-comdat.ll | 46 + test/CodeGen/X86/global-sections.ll | 92 +- test/CodeGen/X86/hoist-invariant-load.ll | 2 +- test/CodeGen/X86/huge-stack-offset.ll | 59 + test/CodeGen/X86/i1narrowfail.ll | 10 + test/CodeGen/X86/ident-metadata.ll | 4 +- test/CodeGen/X86/imul.ll | 110 + test/CodeGen/X86/imul64-lea.ll | 25 - test/CodeGen/X86/inalloca-ctor.ll | 8 +- test/CodeGen/X86/inalloca-invoke.ll | 4 +- test/CodeGen/X86/inalloca-stdcall.ll | 3 +- test/CodeGen/X86/init-priority.ll | 51 + test/CodeGen/X86/inline-asm-flag-clobber.ll | 2 +- test/CodeGen/X86/insertps-O0-bug.ll | 52 + test/CodeGen/X86/large-code-model-isel.ll | 13 + test/CodeGen/X86/lea-2.ll | 2 +- test/CodeGen/X86/logical-load-fold.ll | 53 + test/CodeGen/X86/lower-vec-shift-2.ll | 157 + test/CodeGen/X86/lzcnt-tzcnt.ll | 131 + test/CodeGen/X86/macho-comdat.ll | 2 +- test/CodeGen/X86/masked_memop.ll | 219 + test/CodeGen/X86/mem-intrin-base-reg.ll | 2 +- .../X86/misched-code-difference-with-debug.ll | 90 + test/CodeGen/X86/misched-copy.ll | 8 +- test/CodeGen/X86/misched-crash.ll | 2 +- test/CodeGen/X86/mmx-arg-passing-x86-64.ll | 56 + test/CodeGen/X86/mmx-arg-passing.ll | 45 +- test/CodeGen/X86/mmx-arg-passing2.ll | 28 - test/CodeGen/X86/mmx-arith.ll | 543 +- test/CodeGen/X86/mmx-bitcast-to-i64.ll | 31 - test/CodeGen/X86/mmx-bitcast.ll | 109 + test/CodeGen/X86/mmx-builtins.ll | 1349 - test/CodeGen/X86/mmx-emms.ll | 11 - test/CodeGen/X86/mmx-fold-load.ll | 282 + test/CodeGen/X86/mmx-insert-element.ll | 9 - test/CodeGen/X86/mmx-intrinsics.ll | 1358 + test/CodeGen/X86/mmx-pinsrw.ll | 17 - test/CodeGen/X86/mmx-punpckhdq.ll | 31 - test/CodeGen/X86/mmx-s2v.ll | 15 - test/CodeGen/X86/mmx-shift.ll | 39 - test/CodeGen/X86/mmx-shuffle.ll | 31 - test/CodeGen/X86/movntdq-no-avx.ll | 2 +- test/CodeGen/X86/movtopush.ll | 346 + test/CodeGen/X86/musttail-fastcall.ll | 109 + test/CodeGen/X86/musttail-varargs.ll | 21 + test/CodeGen/X86/named-reg-alloc.ll | 2 +- test/CodeGen/X86/named-reg-notareg.ll | 2 +- test/CodeGen/X86/no-compact-unwind.ll | 64 - test/CodeGen/X86/non-unique-sections.ll | 15 + test/CodeGen/X86/nontemporal-2.ll | 2 +- test/CodeGen/X86/nontemporal.ll | 2 +- test/CodeGen/X86/norex-subreg.ll | 4 +- test/CodeGen/X86/nosse-varargs.ll | 7 +- test/CodeGen/X86/null-streamer.ll | 26 +- test/CodeGen/X86/objc-gc-module-flags.ll | 8 +- test/CodeGen/X86/odr_comdat.ll | 16 - test/CodeGen/X86/palignr.ll | 4 +- test/CodeGen/X86/peep-test-2.ll | 2 +- test/CodeGen/X86/phys_subreg_coalesce-3.ll | 2 +- test/CodeGen/X86/pic_jumptable.ll | 2 +- test/CodeGen/X86/pmul.ll | 121 +- test/CodeGen/X86/pointer-vector.ll | 3 +- test/CodeGen/X86/pr11468.ll | 2 +- test/CodeGen/X86/pr12360.ll | 2 +- test/CodeGen/X86/pr15267.ll | 75 +- test/CodeGen/X86/pr18846.ll | 12 +- test/CodeGen/X86/pr21792.ll | 41 + test/CodeGen/X86/pr22019.ll | 23 + test/CodeGen/X86/pr22103.ll | 19 + test/CodeGen/X86/pre-ra-sched.ll | 2 +- test/CodeGen/X86/prefixdata.ll | 9 +- test/CodeGen/X86/prologuedata.ll | 17 + test/CodeGen/X86/pshufb-mask-comments.ll | 22 + test/CodeGen/X86/psubus.ll | 316 +- test/CodeGen/X86/ragreedy-bug.ll | 48 +- test/CodeGen/X86/ragreedy-hoist-spill.ll | 19 +- .../CodeGen/X86/regalloc-reconcile-broken-hints.ll | 145 + test/CodeGen/X86/remat-phys-dead.ll | 2 +- test/CodeGen/X86/scalar_sse_minmax.ll | 61 +- test/CodeGen/X86/scev-interchange.ll | 2 +- test/CodeGen/X86/segmented-stacks.ll | 123 + test/CodeGen/X86/seh-basic.ll | 175 + test/CodeGen/X86/seh-catch-all.ll | 33 + test/CodeGen/X86/seh-filter.ll | 21 + test/CodeGen/X86/seh-finally.ll | 45 + test/CodeGen/X86/seh-safe-div.ll | 197 + test/CodeGen/X86/selectiondag-crash.ll | 15 + test/CodeGen/X86/shrink-compare.ll | 148 + test/CodeGen/X86/sibcall-4.ll | 4 +- test/CodeGen/X86/sibcall-5.ll | 2 +- test/CodeGen/X86/sibcall-win64.ll | 42 + test/CodeGen/X86/sibcall.ll | 87 +- test/CodeGen/X86/sincos-opt.ll | 5 +- test/CodeGen/X86/sink-blockfreq.ll | 6 +- test/CodeGen/X86/sink-hoist.ll | 2 +- test/CodeGen/X86/sjlj-baseptr.ll | 37 + test/CodeGen/X86/slow-div.ll | 28 + test/CodeGen/X86/slow-incdec.ll | 8 +- test/CodeGen/X86/small-byval-memcpy.ll | 41 +- test/CodeGen/X86/splat-const.ll | 40 + test/CodeGen/X86/sret-implicit.ll | 10 + test/CodeGen/X86/sse-domains.ll | 42 - test/CodeGen/X86/sse-minmax.ll | 152 +- test/CodeGen/X86/sse-scalar-fp-arith.ll | 149 +- test/CodeGen/X86/sse-unaligned-mem-feature.ll | 13 + test/CodeGen/X86/sse2-intrinsics-x86-upgrade.ll | 31 + test/CodeGen/X86/sse2-intrinsics-x86.ll | 32 - test/CodeGen/X86/sse2.ll | 16 +- test/CodeGen/X86/sse3.ll | 51 +- test/CodeGen/X86/sse41-pmovxrm-intrinsics.ll | 123 + test/CodeGen/X86/sse41.ll | 288 +- test/CodeGen/X86/sse4a.ll | 1 + test/CodeGen/X86/sse_partial_update.ll | 66 +- test/CodeGen/X86/stack-align.ll | 22 +- test/CodeGen/X86/stack-folding-fp-avx1.ll | 1811 ++ test/CodeGen/X86/stack-folding-fp-sse42.ll | 1089 + test/CodeGen/X86/stack-folding-int-avx1.ll | 1152 + test/CodeGen/X86/stack-folding-int-avx2.ll | 1200 + test/CodeGen/X86/stack-folding-int-sse42.ll | 1143 + test/CodeGen/X86/stack-folding-xop.ll | 718 + test/CodeGen/X86/stack-probe-size.ll | 78 + test/CodeGen/X86/stack-protector-dbginfo.ll | 144 +- test/CodeGen/X86/stack-protector-weight.ll | 36 + test/CodeGen/X86/stackpointer.ll | 2 +- test/CodeGen/X86/statepoint-call-lowering.ll | 104 + test/CodeGen/X86/statepoint-forward.ll | 107 + test/CodeGen/X86/statepoint-stack-usage.ll | 60 + test/CodeGen/X86/statepoint-stackmap-format.ll | 109 + test/CodeGen/X86/switch-bt.ll | 58 + test/CodeGen/X86/switch-default-only.ll | 14 + test/CodeGen/X86/switch-jump-table.ll | 52 + test/CodeGen/X86/tail-call-win64.ll | 36 + test/CodeGen/X86/tailcall-64.ll | 4 +- test/CodeGen/X86/tailcall-returndup-void.ll | 10 +- test/CodeGen/X86/tls-models.ll | 8 + test/CodeGen/X86/trap.ll | 20 +- test/CodeGen/X86/uint_to_fp-2.ll | 2 +- test/CodeGen/X86/unaligned-32-byte-memops.ll | 288 + test/CodeGen/X86/unknown-location.ll | 26 +- test/CodeGen/X86/utf16-cfstrings.ll | 8 +- test/CodeGen/X86/v2f32.ll | 6 +- test/CodeGen/X86/vaargs.ll | 2 +- test/CodeGen/X86/vec-loadsingles-alignment.ll | 35 + test/CodeGen/X86/vec_cast2.ll | 33 +- test/CodeGen/X86/vec_clear.ll | 13 - test/CodeGen/X86/vec_compare.ll | 52 +- test/CodeGen/X86/vec_extract-avx.ll | 82 + test/CodeGen/X86/vec_extract-mmx.ll | 71 + test/CodeGen/X86/vec_fabs.ll | 2 +- test/CodeGen/X86/vec_fneg.ll | 2 +- test/CodeGen/X86/vec_insert-5.ll | 36 +- test/CodeGen/X86/vec_insert-mmx.ll | 58 + test/CodeGen/X86/vec_loadsingles.ll | 153 +- test/CodeGen/X86/vec_split.ll | 6 +- test/CodeGen/X86/vector-blend.ll | 391 +- test/CodeGen/X86/vector-ctpop.ll | 159 + test/CodeGen/X86/vector-idiv.ll | 436 +- test/CodeGen/X86/vector-sext.ll | 226 +- test/CodeGen/X86/vector-shuffle-128-v16.ll | 636 +- test/CodeGen/X86/vector-shuffle-128-v2.ll | 187 +- test/CodeGen/X86/vector-shuffle-128-v4.ll | 819 +- test/CodeGen/X86/vector-shuffle-128-v8.ll | 664 +- test/CodeGen/X86/vector-shuffle-256-v16.ll | 475 +- test/CodeGen/X86/vector-shuffle-256-v32.ll | 728 +- test/CodeGen/X86/vector-shuffle-256-v4.ll | 268 +- test/CodeGen/X86/vector-shuffle-256-v8.ll | 505 +- test/CodeGen/X86/vector-shuffle-512-v16.ll | 40 + test/CodeGen/X86/vector-shuffle-512-v8.ll | 172 +- test/CodeGen/X86/vector-shuffle-combining.ll | 1154 +- test/CodeGen/X86/vector-shuffle-mmx.ll | 106 + test/CodeGen/X86/vector-shuffle-sse1.ll | 34 +- test/CodeGen/X86/vector-trunc.ll | 223 + test/CodeGen/X86/vector-zext.ll | 371 +- test/CodeGen/X86/vector-zmov.ll | 37 + test/CodeGen/X86/viabs.ll | 8 +- test/CodeGen/X86/vselect-2.ll | 53 +- test/CodeGen/X86/vselect-avx.ll | 31 +- test/CodeGen/X86/vselect-minmax.ll | 2790 +++ test/CodeGen/X86/vselect.ll | 47 +- test/CodeGen/X86/vshift-4.ll | 2 +- test/CodeGen/X86/vshift-6.ll | 2 +- test/CodeGen/X86/widen_conversions.ll | 2 +- test/CodeGen/X86/widen_load-0.ll | 2 +- test/CodeGen/X86/widen_load-1.ll | 4 +- test/CodeGen/X86/widen_load-2.ll | 20 +- test/CodeGen/X86/widen_shuffle-1.ll | 4 +- test/CodeGen/X86/win64_alloca_dynalloca.ll | 38 +- test/CodeGen/X86/win64_call_epi.ll | 2 +- test/CodeGen/X86/win64_eh.ll | 41 +- test/CodeGen/X86/win64_frame.ll | 122 + test/CodeGen/X86/win_chkstk.ll | 5 + test/CodeGen/X86/win_cst_pool.ll | 10 +- test/CodeGen/X86/win_eh_prepare.ll | 80 + test/CodeGen/X86/x32-lea-1.ll | 10 + test/CodeGen/X86/x86-64-and-mask.ll | 2 +- test/CodeGen/X86/x86-64-baseptr.ll | 26 + test/CodeGen/X86/x86-64-psub.ll | 2 +- test/CodeGen/X86/x86-inline-asm-validation.ll | 34 + test/CodeGen/X86/x86-shifts.ll | 2 +- test/CodeGen/X86/xaluo.ll | 2 +- test/CodeGen/X86/xop-intrinsics-x86_64.ll | 130 +- test/CodeGen/X86/xor.ll | 6 +- test/CodeGen/XCore/dwarf_debug.ll | 28 +- test/DebugInfo/2009-10-16-Phi.ll | 2 +- test/DebugInfo/2009-11-03-InsertExtractValue.ll | 14 +- test/DebugInfo/2009-11-05-DeadGlobalVariable.ll | 28 +- .../DebugInfo/2009-11-06-NamelessGlobalVariable.ll | 16 +- test/DebugInfo/2009-11-10-CurrentFn.ll | 32 +- test/DebugInfo/2010-01-05-DbgScope.ll | 24 +- test/DebugInfo/2010-03-12-llc-crash.ll | 24 +- test/DebugInfo/2010-03-19-DbgDeclare.ll | 14 +- test/DebugInfo/2010-03-24-MemberFn.ll | 62 +- test/DebugInfo/2010-03-30-InvalidDbgInfoCrash.ll | 48 +- test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll | 92 +- test/DebugInfo/2010-04-19-FramePtr.ll | 26 +- test/DebugInfo/2010-05-03-DisableFramePtr.ll | 42 +- test/DebugInfo/2010-05-03-OriginDIE.ll | 94 +- test/DebugInfo/2010-05-10-MultipleCU.ll | 44 +- test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll | 64 +- test/DebugInfo/2010-07-19-Crash.ll | 32 +- test/DebugInfo/2010-10-01-crash.ll | 20 +- test/DebugInfo/AArch64/big-endian-dump.ll | 12 +- test/DebugInfo/AArch64/big-endian.ll | 22 +- test/DebugInfo/AArch64/cfi-eof-prologue.ll | 112 + test/DebugInfo/AArch64/coalescing.ll | 65 + test/DebugInfo/AArch64/dwarfdump.ll | 22 +- test/DebugInfo/AArch64/frameindices.ll | 257 + test/DebugInfo/AArch64/little-endian-dump.ll | 12 +- test/DebugInfo/AArch64/processes-relocations.ll | 12 +- test/DebugInfo/AArch64/struct_by_value.ll | 44 +- test/DebugInfo/ARM/PR16736.ll | 56 +- test/DebugInfo/ARM/big-endian-dump.ll | 16 +- test/DebugInfo/ARM/cfi-eof-prologue.ll | 115 + test/DebugInfo/ARM/line.test | 7 + test/DebugInfo/ARM/little-endian-dump.ll | 16 +- test/DebugInfo/ARM/lowerbdgdeclare_vla.ll | 82 +- test/DebugInfo/ARM/processes-relocations.ll | 12 +- test/DebugInfo/ARM/s-super-register.ll | 44 +- test/DebugInfo/ARM/sectionorder.ll | 10 +- test/DebugInfo/ARM/selectiondag-deadcode.ll | 14 +- test/DebugInfo/ARM/tls.ll | 20 +- test/DebugInfo/COFF/asan-module-ctor.ll | 25 +- .../COFF/asan-module-without-functions.ll | 12 +- test/DebugInfo/COFF/asm.ll | 38 +- test/DebugInfo/COFF/cpp-mangling.ll | 26 +- test/DebugInfo/COFF/multifile.ll | 48 +- test/DebugInfo/COFF/multifunction.ll | 52 +- test/DebugInfo/COFF/simple.ll | 36 +- .../COFF/tail-call-without-lexical-scopes.ll | 32 +- test/DebugInfo/Inputs/gmlt.ll | 40 +- test/DebugInfo/Inputs/line.ll | 55 + test/DebugInfo/Mips/delay-slot.ll | 40 +- test/DebugInfo/Mips/fn-call-line.ll | 84 + test/DebugInfo/Mips/processes-relocations.ll | 12 +- test/DebugInfo/PDB/Inputs/empty.cpp | 7 + test/DebugInfo/PDB/Inputs/empty.pdb | Bin 0 -> 102400 bytes test/DebugInfo/PDB/Inputs/symbolformat-fpo.cpp | 6 + test/DebugInfo/PDB/Inputs/symbolformat.cpp | 53 + test/DebugInfo/PDB/Inputs/symbolformat.pdb | Bin 0 -> 143360 bytes test/DebugInfo/PDB/lit.local.cfg | 1 + test/DebugInfo/PDB/pdbdump-flags.test | 32 + test/DebugInfo/PDB/pdbdump-symbol-format.test | 49 + test/DebugInfo/PR20038.ll | 94 +- test/DebugInfo/PowerPC/line.test | 7 + test/DebugInfo/PowerPC/processes-relocations.ll | 12 +- test/DebugInfo/PowerPC/tls-fission.ll | 18 +- test/DebugInfo/PowerPC/tls.ll | 18 +- test/DebugInfo/Sparc/gnu-window-save.ll | 28 +- test/DebugInfo/Sparc/processes-relocations.ll | 12 +- test/DebugInfo/SystemZ/processes-relocations.ll | 12 +- test/DebugInfo/SystemZ/variable-loc.ll | 60 +- test/DebugInfo/X86/2010-04-13-PubType.ll | 46 +- test/DebugInfo/X86/2010-08-10-DbgConstant.ll | 31 - test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll | 36 +- test/DebugInfo/X86/2011-12-16-BadStructRef.ll | 172 +- test/DebugInfo/X86/DW_AT_byte_size.ll | 38 +- test/DebugInfo/X86/DW_AT_linkage_name.ll | 80 +- test/DebugInfo/X86/DW_AT_location-reference.ll | 52 +- test/DebugInfo/X86/DW_AT_object_pointer.ll | 82 +- test/DebugInfo/X86/DW_AT_specification.ll | 40 +- test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll | 24 +- test/DebugInfo/X86/DW_TAG_friend.ll | 56 +- test/DebugInfo/X86/aligned_stack_var.ll | 30 +- test/DebugInfo/X86/arange.ll | 30 +- test/DebugInfo/X86/arguments.ll | 54 +- test/DebugInfo/X86/array.ll | 90 +- test/DebugInfo/X86/array2.ll | 82 +- test/DebugInfo/X86/asm-macro-line-number.s | 20 + test/DebugInfo/X86/block-capture.ll | 226 +- test/DebugInfo/X86/byvalstruct.ll | 88 +- test/DebugInfo/X86/c-type-units.ll | 20 +- test/DebugInfo/X86/coff_debug_info_type.ll | 26 +- test/DebugInfo/X86/coff_relative_names.ll | 24 +- test/DebugInfo/X86/concrete_out_of_line.ll | 106 +- test/DebugInfo/X86/constant-aggregate.ll | 118 + test/DebugInfo/X86/cu-ranges-odr.ll | 70 +- test/DebugInfo/X86/cu-ranges.ll | 38 +- test/DebugInfo/X86/data_member_location.ll | 34 +- test/DebugInfo/X86/dbg-at-specficiation.ll | 22 +- test/DebugInfo/X86/dbg-byval-parameter.ll | 46 +- test/DebugInfo/X86/dbg-const-int.ll | 34 +- test/DebugInfo/X86/dbg-const.ll | 40 +- test/DebugInfo/X86/dbg-declare-arg.ll | 116 +- test/DebugInfo/X86/dbg-declare.ll | 52 +- test/DebugInfo/X86/dbg-file-name.ll | 20 +- test/DebugInfo/X86/dbg-i128-const.ll | 36 +- test/DebugInfo/X86/dbg-merge-loc-entry.ll | 70 +- test/DebugInfo/X86/dbg-prolog-end.ll | 48 +- test/DebugInfo/X86/dbg-subrange.ll | 36 +- test/DebugInfo/X86/dbg-value-const-byref.ll | 60 +- test/DebugInfo/X86/dbg-value-dag-combine.ll | 50 +- test/DebugInfo/X86/dbg-value-inlined-parameter.ll | 90 +- test/DebugInfo/X86/dbg-value-isel.ll | 54 +- test/DebugInfo/X86/dbg-value-location.ll | 56 +- test/DebugInfo/X86/dbg-value-range.ll | 48 +- test/DebugInfo/X86/dbg-value-terminator.ll | 40 +- test/DebugInfo/X86/dbg_value_direct.ll | 62 +- test/DebugInfo/X86/debug-dead-local-var.ll | 44 +- test/DebugInfo/X86/debug-info-access.ll | 84 +- .../X86/debug-info-block-captured-self.ll | 64 +- test/DebugInfo/X86/debug-info-blocks.ll | 246 +- test/DebugInfo/X86/debug-info-static-member.ll | 66 +- test/DebugInfo/X86/debug-loc-asan.ll | 36 +- test/DebugInfo/X86/debug-loc-offset.ll | 76 +- test/DebugInfo/X86/debug-ranges-offset.ll | 82 +- test/DebugInfo/X86/debug_frame.ll | 16 +- test/DebugInfo/X86/decl-derived-member.ll | 163 +- test/DebugInfo/X86/discriminator.ll | 34 +- .../DebugInfo/X86/dwarf-aranges-no-dwarf-labels.ll | 58 +- test/DebugInfo/X86/dwarf-aranges.ll | 34 +- test/DebugInfo/X86/dwarf-public-names.ll | 80 +- test/DebugInfo/X86/dwarf-pubnames-split.ll | 24 +- test/DebugInfo/X86/earlydup-crash.ll | 98 +- test/DebugInfo/X86/elf-names.ll | 102 +- test/DebugInfo/X86/empty-and-one-elem-array.ll | 68 +- test/DebugInfo/X86/empty-array.ll | 40 +- test/DebugInfo/X86/ending-run.ll | 38 +- test/DebugInfo/X86/enum-class.ll | 42 +- test/DebugInfo/X86/enum-fwd-decl.ll | 16 +- test/DebugInfo/X86/fission-cu.ll | 16 +- test/DebugInfo/X86/fission-hash.ll | 10 +- test/DebugInfo/X86/fission-inline.ll | 60 +- test/DebugInfo/X86/fission-ranges.ll | 104 +- test/DebugInfo/X86/float_const.ll | 55 + test/DebugInfo/X86/formal_parameter.ll | 48 +- test/DebugInfo/X86/generate-odr-hash.ll | 116 +- test/DebugInfo/X86/ghost-sdnode-dbgvalues.ll | 82 +- test/DebugInfo/X86/gnu-public-names-empty.ll | 10 +- test/DebugInfo/X86/gnu-public-names.ll | 124 +- test/DebugInfo/X86/inline-member-function.ll | 62 +- test/DebugInfo/X86/inline-seldag-test.ll | 50 +- test/DebugInfo/X86/instcombine-instrinsics.ll | 52 +- test/DebugInfo/X86/lexical_block.ll | 36 +- test/DebugInfo/X86/line-info.ll | 42 +- test/DebugInfo/X86/line.test | 1 + test/DebugInfo/X86/linkage-name.ll | 50 +- test/DebugInfo/X86/low-pc-cu.ll | 24 +- test/DebugInfo/X86/memberfnptr.ll | 44 + test/DebugInfo/X86/misched-dbg-value.ll | 176 +- test/DebugInfo/X86/multiple-aranges.ll | 28 +- test/DebugInfo/X86/multiple-at-const-val.ll | 58 +- test/DebugInfo/X86/nodebug_with_debug_loc.ll | 84 +- test/DebugInfo/X86/nondefault-subrange-array.ll | 40 +- test/DebugInfo/X86/nophysreg.ll | 203 + test/DebugInfo/X86/objc-fwd-decl.ll | 26 +- test/DebugInfo/X86/objc-property-void.ll | 64 +- test/DebugInfo/X86/op_deref.ll | 67 +- test/DebugInfo/X86/parameters.ll | 74 +- test/DebugInfo/X86/pieces-1.ll | 58 +- test/DebugInfo/X86/pieces-2.ll | 68 +- test/DebugInfo/X86/pieces-3.ll | 84 +- test/DebugInfo/X86/pointer-type-size.ll | 26 +- test/DebugInfo/X86/pr11300.ll | 64 +- test/DebugInfo/X86/pr12831.ll | 330 +- test/DebugInfo/X86/pr13303.ll | 24 +- test/DebugInfo/X86/pr19307.ll | 122 +- test/DebugInfo/X86/processes-relocations.ll | 12 +- test/DebugInfo/X86/prologue-stack.ll | 26 +- test/DebugInfo/X86/recursive_inlining.ll | 156 +- test/DebugInfo/X86/ref_addr_relocation.ll | 32 +- test/DebugInfo/X86/reference-argument.ll | 142 +- test/DebugInfo/X86/rvalue-ref.ll | 34 +- test/DebugInfo/X86/sret.ll | 290 +- test/DebugInfo/X86/sroasplit-1.ll | 97 + test/DebugInfo/X86/sroasplit-2.ll | 102 + test/DebugInfo/X86/sroasplit-3.ll | 63 + test/DebugInfo/X86/sroasplit-4.ll | 146 + test/DebugInfo/X86/sroasplit-5.ll | 91 + .../X86/stmt-list-multiple-compile-units.ll | 50 +- test/DebugInfo/X86/stmt-list.ll | 16 +- test/DebugInfo/X86/stringpool.ll | 16 +- test/DebugInfo/X86/struct-loc.ll | 22 +- test/DebugInfo/X86/subrange-type.ll | 36 +- test/DebugInfo/X86/subreg.ll | 29 +- test/DebugInfo/X86/subregisters.ll | 80 +- test/DebugInfo/X86/template.ll | 122 +- test/DebugInfo/X86/tls.ll | 38 +- test/DebugInfo/X86/type_units_with_addresses.ll | 74 +- test/DebugInfo/X86/union-const.ll | 66 + test/DebugInfo/X86/union-template.ll | 62 +- test/DebugInfo/X86/vector.ll | 24 +- test/DebugInfo/X86/vla.ll | 68 +- test/DebugInfo/array.ll | 36 +- test/DebugInfo/block-asan.ll | 87 + test/DebugInfo/bug_null_debuginfo.ll | 6 +- test/DebugInfo/constant-pointers.ll | 38 +- test/DebugInfo/cross-cu-inlining.ll | 54 +- test/DebugInfo/cross-cu-linkonce-distinct.ll | 52 +- test/DebugInfo/cross-cu-linkonce.ll | 48 +- test/DebugInfo/cu-range-hole.ll | 38 +- test/DebugInfo/cu-ranges.ll | 42 +- test/DebugInfo/dead-argument-order.ll | 46 +- test/DebugInfo/debug-info-always-inline.ll | 60 +- test/DebugInfo/debug-info-qualifiers.ll | 80 +- test/DebugInfo/debuginfofinder-multiple-cu.ll | 34 +- test/DebugInfo/duplicate_inline.ll | 117 - test/DebugInfo/dwarf-public-names.ll | 80 +- test/DebugInfo/dwarfdump-debug-frame-simple.test | 24 +- test/DebugInfo/empty.ll | 10 +- test/DebugInfo/enum-types.ll | 60 +- test/DebugInfo/enum.ll | 52 +- test/DebugInfo/global-with-type-context.ll | 74 - test/DebugInfo/global.ll | 28 +- test/DebugInfo/incorrect-variable-debugloc.ll | 110 +- test/DebugInfo/incorrect-variable-debugloc1.ll | 77 + test/DebugInfo/inheritance.ll | 102 +- test/DebugInfo/inline-debug-info-multiret.ll | 74 +- test/DebugInfo/inline-debug-info.ll | 76 +- test/DebugInfo/inline-no-debug-info.ll | 31 +- test/DebugInfo/inline-scopes.ll | 70 +- test/DebugInfo/inlined-arguments.ll | 62 +- test/DebugInfo/inlined-vars.ll | 52 +- test/DebugInfo/location-verifier.ll | 33 + test/DebugInfo/lto-comp-dir.ll | 44 +- test/DebugInfo/member-order.ll | 44 +- test/DebugInfo/member-pointers.ll | 30 +- test/DebugInfo/missing-abstract-variable.ll | 98 +- test/DebugInfo/multiline.ll | 82 + test/DebugInfo/namespace.ll | 156 +- test/DebugInfo/namespace_function_definition.ll | 24 +- .../namespace_inline_function_definition.ll | 44 +- test/DebugInfo/nodebug.ll | 24 +- test/DebugInfo/piece-verifier.ll | 54 + test/DebugInfo/restrict.ll | 34 +- test/DebugInfo/sugared-constants.ll | 66 +- test/DebugInfo/template-recursive-void.ll | 76 +- test/DebugInfo/tu-composite.ll | 134 +- test/DebugInfo/tu-member-pointer.ll | 24 +- test/DebugInfo/two-cus-from-same-file.ll | 64 +- test/DebugInfo/typedef.ll | 22 +- test/DebugInfo/unconditional-branch.ll | 43 +- test/DebugInfo/varargs.ll | 62 +- test/DebugInfo/version.ll | 24 +- test/ExecutionEngine/2002-12-16-ArgTest.ll | 37 - test/ExecutionEngine/2003-01-04-ArgumentBug.ll | 13 - test/ExecutionEngine/2003-01-04-LoopTest.ll | 20 - test/ExecutionEngine/2003-01-04-PhiTest.ll | 12 - test/ExecutionEngine/2003-01-09-SARTest.ll | 11 - test/ExecutionEngine/2003-01-10-FUCOM.ll | 10 - test/ExecutionEngine/2003-01-15-AlignmentTest.ll | 17 - test/ExecutionEngine/2003-05-06-LivenessClobber.ll | 19 - test/ExecutionEngine/2003-05-07-ArgumentTest.ll | 11 - test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll | 15 - test/ExecutionEngine/2003-06-04-bzip2-bug.ll | 19 - test/ExecutionEngine/2003-06-05-PHIBug.ll | 17 - test/ExecutionEngine/2003-08-15-AllocaAssertion.ll | 11 - test/ExecutionEngine/2003-08-21-EnvironmentTest.ll | 21 - .../2003-08-23-RegisterAllocatePhysReg.ll | 34 - ...-10-18-PHINode-ConstantExpr-CondCode-Failure.ll | 23 - test/ExecutionEngine/2005-12-02-TailCallBug.ll | 21 - test/ExecutionEngine/2007-12-10-APIntLoadStore.ll | 19 - test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll | 60 - .../MCJIT/2003-05-11-PHIRegAllocBug.ll | 2 - test/ExecutionEngine/MCJIT/2003-06-04-bzip2-bug.ll | 2 - test/ExecutionEngine/MCJIT/2003-06-05-PHIBug.ll | 2 - .../ExecutionEngine/MCJIT/2010-01-15-UndefValue.ll | 8 - test/ExecutionEngine/MCJIT/eh-lg-pic.ll | 2 +- test/ExecutionEngine/MCJIT/eh-sm-pic.ll | 2 +- test/ExecutionEngine/MCJIT/eh.ll | 2 +- test/ExecutionEngine/MCJIT/multi-module-eh-a.ll | 2 +- .../MCJIT/non-extern-addend-smallcodemodel.ll | 25 - test/ExecutionEngine/OrcJIT/2002-12-16-ArgTest.ll | 37 + .../OrcJIT/2003-01-04-ArgumentBug.ll | 13 + test/ExecutionEngine/OrcJIT/2003-01-04-LoopTest.ll | 20 + test/ExecutionEngine/OrcJIT/2003-01-04-PhiTest.ll | 12 + test/ExecutionEngine/OrcJIT/2003-01-09-SARTest.ll | 11 + test/ExecutionEngine/OrcJIT/2003-01-10-FUCOM.ll | 10 + .../OrcJIT/2003-01-15-AlignmentTest.ll | 17 + .../OrcJIT/2003-05-06-LivenessClobber.ll | 19 + .../OrcJIT/2003-05-07-ArgumentTest.ll | 11 + .../OrcJIT/2003-05-11-PHIRegAllocBug.ll | 13 + .../ExecutionEngine/OrcJIT/2003-06-04-bzip2-bug.ll | 17 + test/ExecutionEngine/OrcJIT/2003-06-05-PHIBug.ll | 15 + .../OrcJIT/2003-08-15-AllocaAssertion.ll | 11 + .../OrcJIT/2003-08-21-EnvironmentTest.ll | 21 + .../OrcJIT/2003-08-23-RegisterAllocatePhysReg.ll | 34 + ...-10-18-PHINode-ConstantExpr-CondCode-Failure.ll | 23 + .../OrcJIT/2005-12-02-TailCallBug.ll | 22 + .../OrcJIT/2007-12-10-APIntLoadStore.ll | 19 + .../OrcJIT/2008-06-05-APInt-OverAShr.ll | 60 + .../OrcJIT/2013-04-04-RelocAddend.ll | 25 + .../OrcJIT/Inputs/cross-module-b.ll | 7 + .../OrcJIT/Inputs/multi-module-b.ll | 7 + .../OrcJIT/Inputs/multi-module-c.ll | 4 + .../OrcJIT/Inputs/multi-module-eh-b.ll | 30 + test/ExecutionEngine/OrcJIT/cross-module-a.ll | 13 + .../OrcJIT/cross-module-sm-pic-a.ll | 14 + test/ExecutionEngine/OrcJIT/eh-lg-pic.ll | 32 + test/ExecutionEngine/OrcJIT/eh-sm-pic.ll | 32 + test/ExecutionEngine/OrcJIT/eh.ll | 32 + test/ExecutionEngine/OrcJIT/fpbitcast.ll | 21 + test/ExecutionEngine/OrcJIT/hello-sm-pic.ll | 12 + test/ExecutionEngine/OrcJIT/hello.ll | 11 + test/ExecutionEngine/OrcJIT/hello2.ll | 17 + test/ExecutionEngine/OrcJIT/lit.local.cfg | 26 + test/ExecutionEngine/OrcJIT/load-object-a.ll | 24 + test/ExecutionEngine/OrcJIT/multi-module-a.ll | 9 + test/ExecutionEngine/OrcJIT/multi-module-eh-a.ll | 35 + .../OrcJIT/multi-module-sm-pic-a.ll | 10 + test/ExecutionEngine/OrcJIT/non-extern-addend.ll | 21 + test/ExecutionEngine/OrcJIT/pr13727.ll | 88 + .../OrcJIT/remote/Inputs/cross-module-b.ll | 7 + .../OrcJIT/remote/Inputs/multi-module-b.ll | 7 + .../OrcJIT/remote/Inputs/multi-module-c.ll | 4 + .../OrcJIT/remote/cross-module-a.ll | 12 + .../OrcJIT/remote/cross-module-sm-pic-a.ll | 14 + test/ExecutionEngine/OrcJIT/remote/lit.local.cfg | 8 + .../OrcJIT/remote/multi-module-a.ll | 9 + .../OrcJIT/remote/multi-module-sm-pic-a.ll | 10 + .../OrcJIT/remote/simpletest-remote.ll | 10 + test/ExecutionEngine/OrcJIT/remote/stubs-remote.ll | 37 + test/ExecutionEngine/OrcJIT/remote/stubs-sm-pic.ll | 37 + .../OrcJIT/remote/test-common-symbols-remote.ll | 88 + .../OrcJIT/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 + .../OrcJIT/remote/test-ptr-reloc-remote.ll | 15 + .../OrcJIT/remote/test-ptr-reloc-sm-pic.ll | 17 + test/ExecutionEngine/OrcJIT/simplesttest.ll | 6 + test/ExecutionEngine/OrcJIT/simpletest.ll | 11 + test/ExecutionEngine/OrcJIT/stubs-sm-pic.ll | 36 + test/ExecutionEngine/OrcJIT/stubs.ll | 35 + test/ExecutionEngine/OrcJIT/test-arith.ll | 34 + test/ExecutionEngine/OrcJIT/test-branch.ll | 12 + .../OrcJIT/test-call-no-external-funcs.ll | 14 + test/ExecutionEngine/OrcJIT/test-call.ll | 21 + test/ExecutionEngine/OrcJIT/test-cast.ll | 109 + .../OrcJIT/test-common-symbols-alignment.ll | 32 + test/ExecutionEngine/OrcJIT/test-common-symbols.ll | 88 + test/ExecutionEngine/OrcJIT/test-constantexpr.ll | 12 + test/ExecutionEngine/OrcJIT/test-data-align.ll | 15 + .../OrcJIT/test-fp-no-external-funcs.ll | 21 + test/ExecutionEngine/OrcJIT/test-fp.ll | 23 + test/ExecutionEngine/OrcJIT/test-global-ctors.ll | 22 + .../OrcJIT/test-global-init-nonzero-sm-pic.ll | 35 + .../OrcJIT/test-global-init-nonzero.ll | 34 + test/ExecutionEngine/OrcJIT/test-global.ll | 34 + test/ExecutionEngine/OrcJIT/test-loadstore.ll | 31 + test/ExecutionEngine/OrcJIT/test-local.ll | 34 + test/ExecutionEngine/OrcJIT/test-logical.ll | 18 + test/ExecutionEngine/OrcJIT/test-loop.ll | 14 + test/ExecutionEngine/OrcJIT/test-phi.ll | 34 + .../OrcJIT/test-ptr-reloc-sm-pic.ll | 17 + test/ExecutionEngine/OrcJIT/test-ptr-reloc.ll | 16 + test/ExecutionEngine/OrcJIT/test-ret.ll | 46 + test/ExecutionEngine/OrcJIT/test-return.ll | 8 + test/ExecutionEngine/OrcJIT/test-setcond-fp.ll | 24 + test/ExecutionEngine/OrcJIT/test-setcond-int.ll | 69 + test/ExecutionEngine/OrcJIT/test-shift.ll | 32 + test/ExecutionEngine/fpbitcast.ll | 21 - test/ExecutionEngine/frem.ll | 2 + test/ExecutionEngine/hello.ll | 11 - test/ExecutionEngine/hello2.ll | 17 - test/ExecutionEngine/simplesttest.ll | 6 - test/ExecutionEngine/simpletest.ll | 11 - test/ExecutionEngine/stubs.ll | 35 - test/ExecutionEngine/test-arith.ll | 34 - test/ExecutionEngine/test-branch.ll | 12 - .../ExecutionEngine/test-call-no-external-funcs.ll | 14 - test/ExecutionEngine/test-call.ll | 21 - test/ExecutionEngine/test-cast.ll | 109 - test/ExecutionEngine/test-common-symbols.ll | 88 - test/ExecutionEngine/test-constantexpr.ll | 12 - test/ExecutionEngine/test-fp-no-external-funcs.ll | 21 - test/ExecutionEngine/test-fp.ll | 23 - test/ExecutionEngine/test-global-init-nonzero.ll | 34 - test/ExecutionEngine/test-global.ll | 34 - test/ExecutionEngine/test-loadstore.ll | 31 - test/ExecutionEngine/test-local.ll | 34 - test/ExecutionEngine/test-logical.ll | 18 - test/ExecutionEngine/test-loop.ll | 14 - test/ExecutionEngine/test-phi.ll | 34 - test/ExecutionEngine/test-ret.ll | 46 - test/ExecutionEngine/test-return.ll | 8 - test/ExecutionEngine/test-setcond-fp.ll | 24 - test/ExecutionEngine/test-setcond-int.ll | 69 - test/ExecutionEngine/test-shift.ll | 32 - test/Feature/NamedMDNode.ll | 4 +- test/Feature/NamedMDNode2.ll | 2 +- test/Feature/callingconventions.ll | 7 + test/Feature/comdat.ll | 10 +- test/Feature/md_on_instruction.ll | 14 +- test/Feature/metadata.ll | 14 +- test/Feature/prologuedata.ll | 18 + test/Feature/seh-nounwind.ll | 32 + test/FileCheck/same.txt | 23 + .../AddressSanitizer/X86/asm_mov.ll | 10 +- .../AddressSanitizer/X86/bug_11395.ll | 14 +- test/Instrumentation/AddressSanitizer/basic.ll | 2 +- .../Instrumentation/AddressSanitizer/debug_info.ll | 38 +- .../AddressSanitizer/do-not-instrument-cstring.ll | 1 + .../AddressSanitizer/do-not-touch-comdat-global.ll | 2 +- .../AddressSanitizer/global_metadata.ll | 20 +- .../AddressSanitizer/instrument-dynamic-allocas.ll | 24 + .../AddressSanitizer/instrument_global.ll | 2 +- .../instrument_initializer_metadata.ll | 8 +- .../keep-instrumented_functions.ll | 23 - .../AddressSanitizer/stack_dynamic_alloca.ll | 42 + .../AddressSanitizer/stack_layout.ll | 20 +- test/Instrumentation/AddressSanitizer/ubsan.ll | 2 +- .../undecidable-dynamic-alloca-1.ll | 23 + test/Instrumentation/DataFlowSanitizer/abilist.ll | 1 + .../DataFlowSanitizer/args-unreachable-bb.ll | 1 + test/Instrumentation/DataFlowSanitizer/arith.ll | 1 + test/Instrumentation/DataFlowSanitizer/call.ll | 1 + .../DataFlowSanitizer/debug-nonzero-labels.ll | 1 + test/Instrumentation/DataFlowSanitizer/debug.ll | 26 +- test/Instrumentation/DataFlowSanitizer/load.ll | 1 + test/Instrumentation/DataFlowSanitizer/memset.ll | 1 + .../DataFlowSanitizer/prefix-rename.ll | 1 + test/Instrumentation/DataFlowSanitizer/store.ll | 1 + .../DataFlowSanitizer/union-large.ll | 1 + test/Instrumentation/DataFlowSanitizer/union.ll | 1 + test/Instrumentation/InstrProfiling/linkage.ll | 46 + test/Instrumentation/InstrProfiling/no-counters.ll | 10 + test/Instrumentation/InstrProfiling/noruntime.ll | 16 + test/Instrumentation/InstrProfiling/platform.ll | 29 + test/Instrumentation/InstrProfiling/profiling.ll | 38 + test/Instrumentation/MemorySanitizer/atomics.ll | 2 + .../MemorySanitizer/check-constant-shadow.ll | 40 +- .../MemorySanitizer/do-not-emit-module-limits.ll | 21 - .../MemorySanitizer/missing_origin.ll | 14 + .../MemorySanitizer/origin-alignment.ll | 73 + .../MemorySanitizer/store-long-origin.ll | 89 + .../MemorySanitizer/store-origin.ll | 50 +- .../MemorySanitizer/wrap_indirect_calls.ll | 60 - .../SanitizerCoverage/coverage-dbg.ll | 50 +- test/Instrumentation/SanitizerCoverage/coverage.ll | 27 +- .../SanitizerCoverage/coverage2-dbg.ll | 62 +- test/Instrumentation/SanitizerCoverage/tracing.ll | 2 +- test/Instrumentation/ThreadSanitizer/capture.ll | 91 + .../ThreadSanitizer/read_from_global.ll | 6 +- test/Instrumentation/ThreadSanitizer/unaligned.ll | 143 + test/Instrumentation/ThreadSanitizer/vptr_read.ll | 6 +- .../Instrumentation/ThreadSanitizer/vptr_update.ll | 6 +- test/JitListener/lit.local.cfg | 2 +- test/JitListener/multiple.ll | 167 + test/JitListener/simple.ll | 54 + test/JitListener/test-common-symbols.ll | 113 - test/JitListener/test-inline.ll | 212 - test/JitListener/test-parameters.ll | 211 - test/LTO/ARM/inline-asm.ll | 9 + test/LTO/ARM/lit.local.cfg | 2 + test/LTO/ARM/runtime-library-subtarget.ll | 18 + test/LTO/Inputs/bcsection.macho.s | 2 - test/LTO/Inputs/bcsection.s | 2 - test/LTO/X86/Inputs/bcsection.macho.s | 2 + test/LTO/X86/Inputs/bcsection.s | 2 + test/LTO/X86/Inputs/invalid.ll.bc | Bin 0 -> 332 bytes test/LTO/X86/Inputs/list-symbols.ll | 4 + test/LTO/X86/attrs.ll | 15 + test/LTO/X86/bcsection.ll | 21 + test/LTO/X86/cfi_endproc.ll | 42 + test/LTO/X86/current-section.ll | 4 + test/LTO/X86/diagnostic-handler-remarks.ll | 40 + test/LTO/X86/invalid.ll | 4 + test/LTO/X86/jump-table-type.ll | 23 + test/LTO/X86/keep-used-puts-during-instcombine.ll | 36 + test/LTO/X86/linkonce_odr_func.ll | 61 + test/LTO/X86/list-symbols.ll | 15 + test/LTO/X86/lit.local.cfg | 2 + test/LTO/X86/no-undefined-puts-when-implemented.ll | 40 + test/LTO/X86/private-symbol.ll | 7 + test/LTO/X86/runtime-library.ll | 27 + test/LTO/X86/set-merged.ll | 36 + test/LTO/X86/symver-asm.ll | 16 + test/LTO/X86/triple-init.ll | 16 + test/LTO/attrs.ll | 15 - test/LTO/bcsection.ll | 21 - test/LTO/cfi_endproc.ll | 37 - test/LTO/current-section.ll | 4 - test/LTO/diagnostic-handler-remarks.ll | 40 - test/LTO/jump-table-type.ll | 23 - test/LTO/keep-used-puts-during-instcombine.ll | 36 - test/LTO/linkonce_odr_func.ll | 51 - test/LTO/lit.local.cfg | 2 - test/LTO/no-undefined-puts-when-implemented.ll | 40 - test/LTO/private-symbol.ll | 7 - test/LTO/runtime-library.ll | 27 - test/LTO/symver-asm.ll | 16 - test/LTO/triple-init.ll | 16 - test/Linker/2006-06-15-GlobalVarAlignment.ll | 8 - test/Linker/2009-09-03-mdnode.ll | 6 +- test/Linker/2009-09-03-mdnode2.ll | 6 +- test/Linker/2011-08-04-DebugLoc.ll | 24 +- test/Linker/2011-08-04-DebugLoc2.ll | 24 +- test/Linker/2011-08-04-Metadata.ll | 28 +- test/Linker/2011-08-04-Metadata2.ll | 24 +- test/Linker/2011-08-18-unique-class-type.ll | 38 +- test/Linker/2011-08-18-unique-class-type2.ll | 38 +- test/Linker/2011-08-18-unique-debug-type.ll | 26 +- test/Linker/2011-08-18-unique-debug-type2.ll | 26 +- test/Linker/DbgDeclare.ll | 56 +- test/Linker/DbgDeclare2.ll | 60 +- test/Linker/Inputs/alignment.ll | 12 + test/Linker/Inputs/apple-version/1.ll | 1 + test/Linker/Inputs/apple-version/2.ll | 1 + test/Linker/Inputs/apple-version/3.ll | 1 + test/Linker/Inputs/apple-version/4.ll | 1 + test/Linker/Inputs/comdat.ll | 12 +- test/Linker/Inputs/comdat2.ll | 2 +- test/Linker/Inputs/comdat3.ll | 2 +- test/Linker/Inputs/comdat4.ll | 2 +- test/Linker/Inputs/comdat5.ll | 16 +- test/Linker/Inputs/comdat8.ll | 2 +- test/Linker/Inputs/comdat9.ll | 5 - test/Linker/Inputs/distinct.ll | 13 + test/Linker/Inputs/ident.a.ll | 4 +- test/Linker/Inputs/ident.b.ll | 2 +- test/Linker/Inputs/mdlocation.ll | 13 + .../Inputs/module-flags-dont-change-others.ll | 8 + test/Linker/Inputs/module-flags-pic-2-b.ll | 2 +- test/Linker/Inputs/opaque.ll | 13 + test/Linker/Inputs/pr21374.ll | 4 + .../replaced-function-matches-first-subprogram.ll | 27 + test/Linker/Inputs/targettriple-a.ll | 2 +- test/Linker/Inputs/targettriple-b.ll | 2 +- test/Linker/Inputs/targettriple-c.ll | 1 + test/Linker/Inputs/testlink.ll | 56 + test/Linker/Inputs/type-unique-alias.ll | 4 + test/Linker/Inputs/type-unique-dst-types2.ll | 3 + test/Linker/Inputs/type-unique-dst-types3.ll | 2 + test/Linker/Inputs/type-unique-inheritance-a.ll | 56 +- test/Linker/Inputs/type-unique-inheritance-b.ll | 84 +- test/Linker/Inputs/type-unique-name.ll | 5 + test/Linker/Inputs/type-unique-opaque.ll | 6 + test/Linker/Inputs/type-unique-simple2-a.ll | 50 +- test/Linker/Inputs/type-unique-simple2-b.ll | 62 +- test/Linker/Inputs/type-unique-unrelated2.ll | 7 + test/Linker/Inputs/type-unique-unrelated3.ll | 7 + test/Linker/Inputs/unique-fwd-decl-b.ll | 4 +- test/Linker/Inputs/unique-fwd-decl-order.ll | 6 + test/Linker/Inputs/visibility.ll | 2 +- test/Linker/alignment.ll | 22 + test/Linker/apple-version.ll | 24 + test/Linker/comdat.ll | 20 +- test/Linker/comdat2.ll | 2 +- test/Linker/comdat3.ll | 2 +- test/Linker/comdat4.ll | 2 +- test/Linker/comdat5.ll | 2 +- test/Linker/comdat6.ll | 15 +- test/Linker/comdat7.ll | 2 +- test/Linker/comdat8.ll | 2 +- test/Linker/comdat9.ll | 24 +- test/Linker/constructor-comdat.ll | 4 +- test/Linker/debug-info-version-a.ll | 10 +- test/Linker/debug-info-version-b.ll | 8 +- test/Linker/distinct-cycles.ll | 13 + test/Linker/distinct.ll | 37 + test/Linker/linkmdnode.ll | 2 +- test/Linker/linkmdnode2.ll | 4 +- test/Linker/linknamedmdnode.ll | 2 +- test/Linker/linknamedmdnode2.ll | 2 +- test/Linker/lto-attributes.ll | 7 +- test/Linker/mdlocation.ll | 34 + test/Linker/metadata-a.ll | 12 +- test/Linker/metadata-b.ll | 4 +- test/Linker/module-flags-1-a.ll | 16 +- test/Linker/module-flags-1-b.ll | 6 +- test/Linker/module-flags-2-a.ll | 4 +- test/Linker/module-flags-2-b.ll | 2 +- test/Linker/module-flags-3-a.ll | 12 +- test/Linker/module-flags-3-b.ll | 4 +- test/Linker/module-flags-4-a.ll | 4 +- test/Linker/module-flags-4-b.ll | 4 +- test/Linker/module-flags-5-a.ll | 2 +- test/Linker/module-flags-5-b.ll | 2 +- test/Linker/module-flags-6-a.ll | 2 +- test/Linker/module-flags-6-b.ll | 2 +- test/Linker/module-flags-7-a.ll | 2 +- test/Linker/module-flags-7-b.ll | 2 +- test/Linker/module-flags-8-a.ll | 12 +- test/Linker/module-flags-8-b.ll | 4 +- test/Linker/module-flags-dont-change-others.ll | 26 + test/Linker/module-flags-pic-1-a.ll | 4 +- test/Linker/module-flags-pic-2-a.ll | 2 +- test/Linker/opaque.ll | 21 + test/Linker/pr21374.ll | 20 + test/Linker/pr21494.ll | 23 + test/Linker/prefixdata.ll | 9 - test/Linker/prologuedata.ll | 21 + .../replaced-function-matches-first-subprogram.ll | 75 + test/Linker/targettriple.ll | 14 +- test/Linker/testlink.ll | 104 + test/Linker/testlink1.ll | 101 - test/Linker/testlink2.ll | 58 - test/Linker/type-unique-alias.ll | 10 + test/Linker/type-unique-dst-types.ll | 19 + test/Linker/type-unique-name.ll | 13 + test/Linker/type-unique-odr-a.ll | 56 +- test/Linker/type-unique-odr-b.ll | 62 +- test/Linker/type-unique-opaque.ll | 16 + test/Linker/type-unique-simple-a.ll | 46 +- test/Linker/type-unique-simple-b.ll | 58 +- test/Linker/type-unique-simple2-a.ll | 98 +- test/Linker/type-unique-simple2-b.ll | 82 +- test/Linker/type-unique-src-type.ll | 24 + test/Linker/type-unique-type-array-a.ll | 78 +- test/Linker/type-unique-type-array-b.ll | 78 +- test/Linker/type-unique-unrelated.ll | 31 + test/Linker/unique-fwd-decl-a.ll | 4 +- test/Linker/unique-fwd-decl-order.ll | 20 + test/Linker/visibility.ll | 4 +- test/Linker/weakextern.ll | 2 +- test/MC/AArch64/adrp-relocation.s | 2 +- test/MC/AArch64/arm64-elf-relocs.s | 2 +- test/MC/AArch64/arm64-tls-relocs.s | 2 +- test/MC/AArch64/dot-req.s | 4 +- test/MC/AArch64/inline-asm-modifiers.s | 2 +- test/MC/AArch64/tls-relocs.s | 2 +- test/MC/ARM/Windows/invalid-relocation.s | 14 + test/MC/ARM/arm-elf-relocation-diagnostics.s | 27 + test/MC/ARM/arm-elf-relocations.s | 37 + test/MC/ARM/arm-load-store-multiple-deprecated.s | 222 + test/MC/ARM/arm-thumb-cpus.s | 3 + test/MC/ARM/basic-arm-instructions.s | 598 +- test/MC/ARM/coff-debugging-secrel.ll | 22 +- test/MC/ARM/cpu-test.s | 17 + test/MC/ARM/diagnostics.s | 80 + test/MC/ARM/directive-arch-iwmmxt.s | 2 +- test/MC/ARM/directive-arch-iwmmxt2.s | 2 +- test/MC/ARM/directive-cpu.s | 3 +- test/MC/ARM/directive-eabi_attribute-diagnostics.s | 5 + test/MC/ARM/directive-eabi_attribute-overwrite.s | 4 +- test/MC/ARM/directive-eabi_attribute.s | 23 +- test/MC/ARM/directive-fpu-diagnostics.s | 10 + test/MC/ARM/dot-req.s | 3 + test/MC/ARM/ldr-pseudo-parse-errors.s | 2 +- test/MC/ARM/move-banked-regs.s | 66 +- test/MC/ARM/pr22395-2.s | 37 + test/MC/ARM/pr22395.s | 63 + test/MC/ARM/thumb-diagnostics.s | 40 +- test/MC/ARM/thumb-load-store-multiple.s | 100 + test/MC/ARM/thumb2-diagnostics.s | 5 +- test/MC/ARM/thumb2-dsp-diag.s | 24 + test/MC/ARM/v8_IT_manual.s | 7 +- test/MC/ARM/virtexts-arm.s | 42 + test/MC/ARM/virtexts-thumb.s | 59 + test/MC/AsmParser/directive_set.s | 4 +- test/MC/COFF/bss_section.ll | 5 +- test/MC/COFF/const-gv-with-rel-init.ll | 4 +- test/MC/COFF/diff.s | 25 + test/MC/COFF/directive-section-characteristics.ll | 6 + test/MC/COFF/global_ctors_dtors.ll | 12 +- test/MC/COFF/initialised-data.ll | 2 +- test/MC/COFF/linker-options.ll | 10 +- test/MC/COFF/section-passthru-flags.s | 4 +- test/MC/COFF/seh-section.s | 74 +- test/MC/COFF/weak-symbol.ll | 48 - test/MC/Disassembler/ARM/arm-tests.txt | 2 +- .../MC/Disassembler/ARM/basic-arm-instructions.txt | 110 +- test/MC/Disassembler/ARM/invalid-virtexts.arm.txt | 10 + test/MC/Disassembler/ARM/move-banked-regs-arm.txt | 66 +- test/MC/Disassembler/ARM/virtexts-arm.txt | 41 + test/MC/Disassembler/ARM/virtexts-thumb.txt | 61 + test/MC/Disassembler/Hexagon/alu32_alu.txt | 84 + test/MC/Disassembler/Hexagon/alu32_perm.txt | 40 + test/MC/Disassembler/Hexagon/alu32_pred.txt | 194 + test/MC/Disassembler/Hexagon/cr.txt | 78 + test/MC/Disassembler/Hexagon/j.txt | 202 + test/MC/Disassembler/Hexagon/jr.txt | 34 + test/MC/Disassembler/Hexagon/ld.txt | 364 + test/MC/Disassembler/Hexagon/lit.local.cfg | 3 + test/MC/Disassembler/Hexagon/memop.txt | 56 + test/MC/Disassembler/Hexagon/nv_j.txt | 136 + test/MC/Disassembler/Hexagon/nv_st.txt | 203 + test/MC/Disassembler/Hexagon/st.txt | 288 + test/MC/Disassembler/Hexagon/system_user.txt | 26 + test/MC/Disassembler/Hexagon/xtype_alu.txt | 395 + test/MC/Disassembler/Hexagon/xtype_bit.txt | 118 + test/MC/Disassembler/Hexagon/xtype_complex.txt | 128 + test/MC/Disassembler/Hexagon/xtype_fp.txt | 146 + test/MC/Disassembler/Hexagon/xtype_mpy.txt | 400 + test/MC/Disassembler/Hexagon/xtype_perm.txt | 104 + test/MC/Disassembler/Hexagon/xtype_pred.txt | 136 + test/MC/Disassembler/Hexagon/xtype_shift.txt | 260 + test/MC/Disassembler/Mips/micromips.txt | 183 + test/MC/Disassembler/Mips/micromips_le.txt | 183 + test/MC/Disassembler/Mips/mips1/valid-mips1-el.txt | 116 + test/MC/Disassembler/Mips/mips1/valid-mips1.txt | 116 + test/MC/Disassembler/Mips/mips1/valid-xfail.txt | 4 + test/MC/Disassembler/Mips/mips2/valid-mips2-el.txt | 159 + test/MC/Disassembler/Mips/mips2/valid-mips2.txt | 159 + test/MC/Disassembler/Mips/mips3/valid-mips3-el.txt | 209 + test/MC/Disassembler/Mips/mips3/valid-mips3.txt | 209 + .../Disassembler/Mips/mips32/valid-mips32-el.txt | 149 + test/MC/Disassembler/Mips/mips32/valid-mips32.txt | 149 + .../Mips/mips32/valid-xfail-mips32.txt | 30 + test/MC/Disassembler/Mips/mips32r2.txt | 3 + .../Mips/mips32r2/valid-mips32r2-le.txt | 172 + .../Disassembler/Mips/mips32r2/valid-mips32r2.txt | 172 + .../Mips/mips32r2/valid-xfail-mips32r2.txt | 83 + test/MC/Disassembler/Mips/mips32r2_le.txt | 3 + .../Mips/mips32r3/valid-mips32r3-le.txt | 169 + .../Disassembler/Mips/mips32r3/valid-mips32r3.txt | 169 + .../Mips/mips32r3/valid-xfail-mips32r3.txt | 83 + .../Mips/mips32r5/valid-mips32r5-le.txt | 169 + .../Disassembler/Mips/mips32r5/valid-mips32r5.txt | 169 + .../Mips/mips32r5/valid-xfail-mips32r5.txt | 83 + .../Mips/mips32r6/valid-mips32r6-el.txt | 148 + .../Disassembler/Mips/mips32r6/valid-mips32r6.txt | 148 + .../Mips/mips32r6/valid-xfail-mips32r6.txt | 15 + test/MC/Disassembler/Mips/mips4/valid-mips4-el.txt | 229 + test/MC/Disassembler/Mips/mips4/valid-mips4.txt | 229 + .../Disassembler/Mips/mips4/valid-xfail-mips4.txt | 42 + .../Disassembler/Mips/mips64/valid-mips64-el.txt | 216 + .../Mips/mips64/valid-mips64-xfail.txt | 80 + test/MC/Disassembler/Mips/mips64/valid-mips64.txt | 216 + .../Mips/mips64r2/valid-mips64r2-el.txt | 237 + .../Disassembler/Mips/mips64r2/valid-mips64r2.txt | 237 + .../Mips/mips64r2/valid-xfail-mips64r2.txt | 76 + .../Mips/mips64r3/valid-mips64r3-el.txt | 234 + .../Disassembler/Mips/mips64r3/valid-mips64r3.txt | 234 + .../Mips/mips64r3/valid-xfail-mips64r3.txt | 76 + .../Mips/mips64r5/valid-mips64r5-el.txt | 234 + .../Disassembler/Mips/mips64r5/valid-mips64r5.txt | 234 + .../Mips/mips64r5/valid-xfail-mips64r5.txt | 76 + .../Mips/mips64r6/valid-mips64r6-el.txt | 166 + .../Disassembler/Mips/mips64r6/valid-mips64r6.txt | 166 + .../Mips/mips64r6/valid-xfail-mips64r6.txt | 20 + .../MC/Disassembler/PowerPC/ppc64-encoding-ext.txt | 21 + test/MC/Disassembler/PowerPC/ppc64-encoding-fp.txt | 18 + .../MC/Disassembler/PowerPC/ppc64-encoding-vmx.txt | 33 + test/MC/Disassembler/PowerPC/ppc64-encoding.txt | 3 + test/MC/Disassembler/PowerPC/qpx.txt | 383 + test/MC/Disassembler/PowerPC/vsx.txt | 9 + test/MC/Disassembler/X86/avx-512.txt | 27 + test/MC/Disassembler/X86/intel-syntax-32.txt | 12 + test/MC/Disassembler/X86/intel-syntax.txt | 20 + test/MC/Disassembler/X86/invalid-cmp-imm.txt | 10 - test/MC/Disassembler/X86/moffs.txt | 106 +- test/MC/Disassembler/X86/prefixes.txt | 15 +- test/MC/Disassembler/X86/simple-tests.txt | 21 + test/MC/Disassembler/X86/x86-32.txt | 52 +- test/MC/Disassembler/X86/x86-64.txt | 42 +- test/MC/ELF/alias.s | 13 + test/MC/ELF/cfi-large-model.s | 27 + test/MC/ELF/cfi-version.ll | 26 +- test/MC/ELF/common-error1.s | 6 + test/MC/ELF/common-error2.s | 6 + test/MC/ELF/relocation-386.s | 3 + test/MC/ELF/section-unique.s | 39 + test/MC/ELF/symver-msvc.s | 59 + test/MC/ELF/type.s | 12 +- test/MC/ELF/uleb.s | 9 +- test/MC/Hexagon/inst_add.ll | 2 +- test/MC/Hexagon/inst_add64.ll | 10 + test/MC/Hexagon/inst_and.ll | 2 +- test/MC/Hexagon/inst_and64.ll | 10 + test/MC/Hexagon/inst_aslh.ll | 10 + test/MC/Hexagon/inst_asrh.ll | 10 + test/MC/Hexagon/inst_cmp_eq.ll | 10 + test/MC/Hexagon/inst_cmp_eqi.ll | 10 + test/MC/Hexagon/inst_cmp_gt.ll | 10 + test/MC/Hexagon/inst_cmp_gti.ll | 10 + test/MC/Hexagon/inst_cmp_lt.ll | 10 + test/MC/Hexagon/inst_cmp_ugt.ll | 10 + test/MC/Hexagon/inst_cmp_ugti.ll | 10 + test/MC/Hexagon/inst_cmp_ult.ll | 10 + test/MC/Hexagon/inst_or.ll | 2 +- test/MC/Hexagon/inst_or64.ll | 10 + test/MC/Hexagon/inst_select.ll | 10 + test/MC/Hexagon/inst_sub.ll | 2 +- test/MC/Hexagon/inst_sub64.ll | 10 + test/MC/Hexagon/inst_sxtb.ll | 10 + test/MC/Hexagon/inst_sxth.ll | 10 + test/MC/Hexagon/inst_xor.ll | 2 +- test/MC/Hexagon/inst_xor64.ll | 10 + test/MC/Hexagon/inst_zxtb.ll | 10 + test/MC/Hexagon/inst_zxth.ll | 10 + test/MC/MachO/AArch64/cfstring.s | 24 + test/MC/MachO/AArch64/classrefs.s | 25 + test/MC/MachO/AArch64/darwin-ARM64-reloc.s | 355 +- test/MC/MachO/AArch64/mergeable.s | 59 + test/MC/MachO/AArch64/reloc-crash.s | 27 + test/MC/MachO/AArch64/reloc-crash2.s | 24 + test/MC/MachO/ARM/static-movt-relocs.s | 57 +- test/MC/MachO/darwin-x86_64-reloc.s | 679 +- test/MC/MachO/linker-options.ll | 6 +- test/MC/MachO/reloc.s | 400 +- test/MC/MachO/x86_64-mergeable.s | 59 + test/MC/MachO/x86_64-symbols.s | 1246 +- test/MC/Mips/cpload.s | 2 +- test/MC/Mips/cpsetup-bad.s | 8 + test/MC/Mips/cpsetup.s | 45 +- test/MC/Mips/do_switch3.s | 2 +- test/MC/Mips/elf_eflags.s | 34 +- test/MC/Mips/elf_reginfo.s | 4 +- test/MC/Mips/micromips-16-bit-instructions.s | 84 +- test/MC/Mips/micromips-alu-instructions.s | 9 + test/MC/Mips/micromips-bad-branches.s | 8 + test/MC/Mips/micromips-branch-fixup.s | 91 + test/MC/Mips/micromips-branch-instructions.s | 20 +- test/MC/Mips/micromips-branch16.s | 69 - test/MC/Mips/micromips-control-instructions.s | 15 + test/MC/Mips/micromips-diagnostic-fixup.s | 2 +- test/MC/Mips/micromips-func-addr.s | 16 + test/MC/Mips/micromips-invalid.s | 44 + test/MC/Mips/micromips-jump-instructions.s | 23 +- test/MC/Mips/micromips-loadstore-instructions.s | 45 + test/MC/Mips/mips-abi-bad.s | 36 +- test/MC/Mips/mips-noat.s | 4 + test/MC/Mips/mips-reginfo-fp64.s | 4 +- test/MC/Mips/mips32r2/valid-xfail.s | 1 - test/MC/Mips/mips32r2/valid.s | 1 + test/MC/Mips/mips32r3/abiflags.s | 37 + test/MC/Mips/mips32r3/invalid-mips64r2.s | 10 + test/MC/Mips/mips32r3/invalid.s | 10 + test/MC/Mips/mips32r3/valid-xfail.s | 308 + test/MC/Mips/mips32r3/valid.s | 236 + test/MC/Mips/mips32r5/abiflags.s | 37 + test/MC/Mips/mips32r5/invalid-mips64r2.s | 10 + test/MC/Mips/mips32r5/invalid.s | 10 + test/MC/Mips/mips32r5/valid-xfail.s | 308 + test/MC/Mips/mips32r5/valid.s | 236 + test/MC/Mips/mips4/invalid-mips64r2.s | 4 - test/MC/Mips/mips4/valid-xfail.s | 8 - test/MC/Mips/mips4/valid.s | 8 + test/MC/Mips/mips5/invalid-mips64r2.s | 4 - test/MC/Mips/mips5/valid-xfail.s | 8 - test/MC/Mips/mips5/valid.s | 8 + test/MC/Mips/mips64-register-names-n32-n64.s | 2 +- test/MC/Mips/mips64-register-names-o32.s | 2 +- test/MC/Mips/mips64/invalid-mips64r2.s | 4 - test/MC/Mips/mips64/valid-xfail.s | 8 - test/MC/Mips/mips64/valid.s | 8 + test/MC/Mips/mips64extins.ll | 2 +- test/MC/Mips/mips64r2/abi-bad.s | 12 +- test/MC/Mips/mips64r2/valid-xfail.s | 5 - test/MC/Mips/mips64r3/abi-bad.s | 5 + test/MC/Mips/mips64r3/abiflags.s | 36 + test/MC/Mips/mips64r3/invalid.s | 10 + test/MC/Mips/mips64r3/valid-xfail.s | 306 + test/MC/Mips/mips64r3/valid.s | 305 + test/MC/Mips/mips64r5/abi-bad.s | 5 + test/MC/Mips/mips64r5/abiflags.s | 36 + test/MC/Mips/mips64r5/invalid.s | 10 + test/MC/Mips/mips64r5/valid-xfail.s | 306 + test/MC/Mips/mips64r5/valid.s | 305 + test/MC/Mips/nabi-regs.s | 4 +- test/MC/Mips/nooddspreg-cmdarg.s | 2 +- test/MC/Mips/nooddspreg.s | 2 +- test/MC/Mips/octeon-instructions.s | 21 + test/MC/Mips/oddspreg.s | 6 +- test/MC/Mips/set-arch.s | 12 + test/MC/Mips/set-at-directive-explicit-at.s | 10 + test/MC/Mips/set-at-directive.s | 31 + test/MC/Mips/set-at-noat-bad-syntax.s | 29 + test/MC/Mips/set-mips-directives-bad.s | 12 + test/MC/Mips/set-mips-directives.s | 24 + test/MC/PowerPC/ppc-reloc.s | 2 + test/MC/PowerPC/ppc64-encoding-ext.s | 33 + test/MC/PowerPC/ppc64-encoding-fp.s | 39 +- test/MC/PowerPC/ppc64-encoding-vmx.s | 43 + test/MC/PowerPC/ppc64-encoding.s | 10 +- test/MC/PowerPC/ppc64-localentry.s | 19 + test/MC/PowerPC/qpx.s | 251 + test/MC/PowerPC/vsx.s | 9 + test/MC/R600/sopp.s | 2 +- test/MC/SystemZ/fixups.s | 119 + test/MC/X86/avx512-encodings.s | 1186 +- test/MC/X86/avx512bw-encoding.s | 73 + test/MC/X86/avx512vl-encoding.s | 449 + test/MC/X86/compact-unwind.s | 72 + test/MC/X86/cstexpr-gotpcrel.ll | 78 + test/MC/X86/i386-darwin-frame-register.ll | 38 + test/MC/X86/intel-syntax-unsized-memory.s | 29 + test/MC/X86/intel-syntax.s | 4 +- test/MC/X86/shuffle-comments.s | 5 + test/MC/X86/validate-inst-att.s | 7 + test/MC/X86/validate-inst-intel.s | 9 + test/MC/X86/x86-32-avx.s | 300 +- test/MC/X86/x86-32-coverage.s | 24950 ++++++------------- test/MC/X86/x86-32.s | 16 +- test/MC/X86/x86-64-avx512bw.s | 752 + test/MC/X86/x86-64-avx512bw_vl.s | 48 + test/MC/X86/x86-64-avx512f_vl.s | 72 + test/MC/X86/x86_64-avx-encoding.s | 672 +- test/MC/X86/x86_64-encoding.s | 12 +- test/MC/X86/x86_64-xop-encoding.s | 64 + test/MC/X86/x86_errors.s | 8 + test/Makefile | 8 +- test/Object/AArch64/yaml2obj-elf-aarch64-rel.yaml | 10 +- test/Object/Inputs/archive-test.a-irix6-mips64el | Bin 0 -> 6608 bytes test/Object/Inputs/macho-invalid-bad-symbol-index | Bin 0 -> 4536 bytes test/Object/Inputs/macho-invalid-getsection-index | Bin 0 -> 316 bytes .../Inputs/macho-invalid-no-size-for-sections | Bin 0 -> 104 bytes ...lid-section-index-getSectionRawFinalSegmentName | Bin 0 -> 4536 bytes .../macho-invalid-section-index-getSectionRawName | Bin 0 -> 4536 bytes .../Inputs/macho-invalid-symbol-name-past-eof | Bin 0 -> 4536 bytes .../Inputs/macho-invalid-too-small-load-command | Bin 0 -> 36 bytes .../macho-invalid-too-small-segment-load-command | Bin 0 -> 104 bytes test/Object/Inputs/macho-invalid-zero-ncmds | Bin 0 -> 32 bytes test/Object/Inputs/macho-no-exports.dylib | Bin 0 -> 4208 bytes test/Object/Inputs/macho-rpath-x86_64 | Bin 0 -> 4296 bytes .../Object/Inputs/macho64-invalid-getsection-index | Bin 0 -> 4536 bytes .../Inputs/macho64-invalid-incomplete-load-command | Bin 0 -> 36 bytes .../Inputs/macho64-invalid-no-size-for-sections | Bin 0 -> 104 bytes .../Inputs/macho64-invalid-too-small-load-command | Bin 0 -> 40 bytes .../macho64-invalid-too-small-segment-load-command | Bin 0 -> 104 bytes test/Object/Inputs/micro-mips.elf-mipsel | Bin 0 -> 2394 bytes test/Object/Inputs/sectionGroup.elf.x86-64 | Bin 0 -> 1512 bytes test/Object/Inputs/thin.a | Bin 0 -> 474 bytes test/Object/Mips/elf-mips64-rel.yaml | 113 + test/Object/Mips/objdump-micro-mips.test | 12 + test/Object/archive-toc.test | 8 + test/Object/elf-unknown-type.test | 10 + test/Object/macho-invalid.test | 51 + test/Object/nm-irix6.test | 27 + test/Object/obj2yaml-sectiongroup.test | 26 + test/Object/obj2yaml.test | 8 - test/Object/objdump-export-list.test | 4 + test/Object/objdump-private-headers.test | 7 + test/Other/2009-03-31-CallGraph.ll | 2 + test/Other/Inputs/utf8-bom-response | 1 + test/Other/Inputs/utf8-response | 1 + test/Other/ResponseFile.ll | 5 + test/Other/new-pass-manager.ll | 292 +- test/Other/pass-pipeline-parsing.ll | 132 +- test/SymbolRewriter/rewrite.ll | 33 + test/SymbolRewriter/rewrite.map | 20 + test/Transforms/AddDiscriminators/basic.ll | 34 +- test/Transforms/AddDiscriminators/first-only.ll | 58 +- test/Transforms/AddDiscriminators/multiple.ll | 34 +- .../AddDiscriminators/no-discriminators.ll | 44 +- test/Transforms/ArgumentPromotion/control-flow2.ll | 5 +- test/Transforms/ArgumentPromotion/dbg.ll | 10 +- test/Transforms/ArgumentPromotion/reserve-tbaa.ll | 26 +- test/Transforms/BBVectorize/loop1.ll | 2 +- test/Transforms/BBVectorize/metadata.ll | 8 +- test/Transforms/BDCE/basic.ll | 348 + test/Transforms/BDCE/dce-pure.ll | 33 + test/Transforms/BDCE/order.ll | 37 + .../CodeGenPrepare/statepoint-relocate.ll | 88 + test/Transforms/ConstProp/InsertElement.ll | 12 + test/Transforms/ConstProp/insertvalue.ll | 9 + test/Transforms/CorrelatedValuePropagation/icmp.ll | 63 + test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll | 80 +- test/Transforms/DeadArgElim/aggregates.ll | 162 + test/Transforms/DeadArgElim/dbginfo.ll | 44 +- .../2011-03-25-DSEMiscompile.ll | 6 +- .../Transforms/DeadStoreElimination/inst-limits.ll | 30 +- test/Transforms/DebugIR/crash.ll | 42 - test/Transforms/DebugIR/exception.ll | 127 - test/Transforms/DebugIR/function.ll | 51 - test/Transforms/DebugIR/simple-addrspace.ll | 11 - test/Transforms/DebugIR/simple.ll | 25 - test/Transforms/DebugIR/struct.ll | 24 - test/Transforms/DebugIR/vector.ll | 93 - test/Transforms/EarlyCSE/AArch64/intrinsics.ll | 232 + test/Transforms/EarlyCSE/AArch64/lit.local.cfg | 5 + test/Transforms/EarlyCSE/basic.ll | 12 +- .../Transforms/GCOVProfiling/function-numbering.ll | 30 +- test/Transforms/GCOVProfiling/global-ctor.ll | 34 +- test/Transforms/GCOVProfiling/linezero.ll | 100 +- test/Transforms/GCOVProfiling/linkagename.ll | 22 +- test/Transforms/GCOVProfiling/return-block.ll | 66 + test/Transforms/GCOVProfiling/version.ll | 24 +- test/Transforms/GVN/cond_br2.ll | 12 +- test/Transforms/GVN/condprop.ll | 48 + test/Transforms/GVN/edge.ll | 110 + test/Transforms/GVN/fpmath.ll | 4 +- test/Transforms/GVN/invariant-load.ll | 40 +- .../GVN/load-from-unreachable-predecessor.ll | 20 + test/Transforms/GVN/load-pre-nonlocal.ll | 12 +- test/Transforms/GVN/noalias.ll | 6 +- test/Transforms/GVN/pre-gep-load.ll | 49 + test/Transforms/GVN/pre-no-cost-phi.ll | 31 + test/Transforms/GVN/preserve-tbaa.ll | 8 +- test/Transforms/GVN/range.ll | 32 +- test/Transforms/GVN/tbaa.ll | 69 +- test/Transforms/GVN/volatile.ll | 157 + test/Transforms/GlobalDCE/pr20981.ll | 4 +- test/Transforms/GlobalOpt/2009-03-05-dbg.ll | 48 +- .../GlobalOpt/externally-initialized-global-ctr.ll | 2 +- test/Transforms/GlobalOpt/metadata.ll | 16 +- test/Transforms/GlobalOpt/pr21191.ll | 8 +- test/Transforms/GlobalOpt/preserve-comdats.ll | 6 +- test/Transforms/IRCE/bug-mismatched-types.ll | 66 + test/Transforms/IRCE/decrementing-loop.ll | 43 + test/Transforms/IRCE/low-becount.ll | 32 + test/Transforms/IRCE/multiple-access-no-preloop.ll | 66 + test/Transforms/IRCE/not-likely-taken.ll | 40 + test/Transforms/IRCE/single-access-no-preloop.ll | 116 + test/Transforms/IRCE/single-access-with-preloop.ll | 71 + test/Transforms/IRCE/unhandled.ll | 37 + test/Transforms/IRCE/with-parent-loops.ll | 345 + .../IndVarSimplify/2011-09-10-widen-nsw.ll | 2 +- .../IndVarSimplify/backedge-on-min-max.ll | 453 + test/Transforms/IndVarSimplify/overflowcheck.ll | 2 +- test/Transforms/IndVarSimplify/pr20680.ll | 4 +- test/Transforms/IndVarSimplify/pr22222.ll | 46 + test/Transforms/IndVarSimplify/sharpen-range.ll | 2 +- .../IndVarSimplify/strengthen-overflow.ll | 108 + .../IndVarSimplify/use-range-metadata.ll | 2 +- test/Transforms/Inline/alloca-dbgdeclare.ll | 141 + .../Inline/debug-info-duplicate-calls.ll | 121 + test/Transforms/Inline/debug-invoke.ll | 14 +- test/Transforms/Inline/ignore-debug-info.ll | 12 +- test/Transforms/Inline/inline-fast-math-flags.ll | 34 + test/Transforms/Inline/inline-fp.ll | 136 + test/Transforms/Inline/inline-indirect.ll | 19 + test/Transforms/Inline/inline-vla.ll | 2 +- test/Transforms/Inline/inline_dbg_declare.ll | 97 + test/Transforms/Inline/noalias-calls.ll | 12 +- test/Transforms/Inline/noalias-cs.ll | 68 +- test/Transforms/Inline/noalias.ll | 18 +- test/Transforms/Inline/noalias2.ll | 42 +- test/Transforms/Inline/optimization-remarks.ll | 2 +- test/Transforms/Inline/pr21206.ll | 8 +- .../InstCombine/2008-05-23-CompareFold.ll | 5 +- test/Transforms/InstCombine/2008-11-08-FCmp.ll | 7 + .../InstCombine/2011-06-13-nsw-alloca.ll | 3 +- test/Transforms/InstCombine/AddOverFlow.ll | 4 +- test/Transforms/InstCombine/LandingPadClauses.ll | 52 + test/Transforms/InstCombine/add2.ll | 10 +- test/Transforms/InstCombine/addnegneg.ll | 1 - test/Transforms/InstCombine/alias-recursion.ll | 24 + test/Transforms/InstCombine/aligned-altivec.ll | 131 + test/Transforms/InstCombine/aligned-qpx.ll | 162 + test/Transforms/InstCombine/and-compare.ll | 8 +- test/Transforms/InstCombine/and-xor-merge.ll | 11 +- .../InstCombine/apint-call-cast-target.ll | 9 +- .../InstCombine/bitcast-alias-function.ll | 15 +- test/Transforms/InstCombine/bitcast-store.ll | 10 +- test/Transforms/InstCombine/bswap-fold.ll | 184 +- test/Transforms/InstCombine/call-cast-target.ll | 49 +- test/Transforms/InstCombine/canonicalize_branch.ll | 8 +- test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll | 454 + test/Transforms/InstCombine/cast.ll | 29 +- test/Transforms/InstCombine/cast_ptr.ll | 23 +- test/Transforms/InstCombine/debug-line.ll | 22 +- test/Transforms/InstCombine/debuginfo.ll | 58 +- test/Transforms/InstCombine/div.ll | 43 +- test/Transforms/InstCombine/fast-math.ll | 10 +- test/Transforms/InstCombine/fcmp.ll | 82 + .../Transforms/InstCombine/float-shrink-compare.ll | 38 + test/Transforms/InstCombine/fpcast.ll | 12 + test/Transforms/InstCombine/gc.relocate.ll | 20 + test/Transforms/InstCombine/gep-sext.ll | 61 + test/Transforms/InstCombine/gepphigep.ll | 44 + test/Transforms/InstCombine/getelementptr.ll | 4 +- test/Transforms/InstCombine/icmp-range.ll | 8 +- test/Transforms/InstCombine/icmp.ll | 51 + test/Transforms/InstCombine/intrinsics.ll | 122 +- test/Transforms/InstCombine/load-cmp.ll | 8 +- test/Transforms/InstCombine/load.ll | 53 +- test/Transforms/InstCombine/loadstore-metadata.ll | 39 +- test/Transforms/InstCombine/malloc-free-delete.ll | 27 +- test/Transforms/InstCombine/max-of-nots.ll | 68 + test/Transforms/InstCombine/mem-gep-zidx.ll | 48 + test/Transforms/InstCombine/memcpy_chk-1.ll | 49 +- test/Transforms/InstCombine/memmove_chk-1.ll | 36 +- test/Transforms/InstCombine/memset_chk-1.ll | 45 +- test/Transforms/InstCombine/minnum.ll | 18 +- test/Transforms/InstCombine/mul.ll | 91 + test/Transforms/InstCombine/narrow-switch.ll | 30 + test/Transforms/InstCombine/not-fcmp.ll | 7 +- test/Transforms/InstCombine/not.ll | 8 +- test/Transforms/InstCombine/or-xor.ll | 36 +- test/Transforms/InstCombine/or.ll | 10 + test/Transforms/InstCombine/pr12251.ll | 2 +- test/Transforms/InstCombine/pr12338.ll | 2 +- test/Transforms/InstCombine/pr21199.ll | 25 + test/Transforms/InstCombine/pr21210.ll | 50 + test/Transforms/InstCombine/pr21651.ll | 20 + test/Transforms/InstCombine/pr21891.ll | 18 + test/Transforms/InstCombine/range-check.ll | 159 + test/Transforms/InstCombine/select-cmp-br.ll | 155 + .../Transforms/InstCombine/select-cmp-cttz-ctlz.ll | 327 + test/Transforms/InstCombine/select.ll | 257 +- test/Transforms/InstCombine/shift.ll | 58 +- test/Transforms/InstCombine/signext.ll | 27 +- test/Transforms/InstCombine/sitofp.ll | 169 +- test/Transforms/InstCombine/statepoint.ll | 52 + test/Transforms/InstCombine/store.ll | 10 +- test/Transforms/InstCombine/stpcpy_chk-1.ll | 55 +- test/Transforms/InstCombine/strcpy_chk-1.ll | 59 +- test/Transforms/InstCombine/strncpy_chk-1.ll | 45 +- test/Transforms/InstCombine/struct-assign-tbaa.ll | 20 +- test/Transforms/InstCombine/type_pun.ll | 137 + .../InstCombine/unordered-fcmp-select.ll | 125 + test/Transforms/InstCombine/vec_demanded_elts.ll | 27 + test/Transforms/InstCombine/xor.ll | 86 +- test/Transforms/InstMerge/st_sink_barrier_call.ll | 43 + test/Transforms/InstMerge/st_sink_bugfix_22613.ll | 106 + .../InstMerge/st_sink_no_barrier_call.ll | 45 + .../InstMerge/st_sink_no_barrier_load.ll | 43 + .../InstMerge/st_sink_no_barrier_store.ll | 42 + test/Transforms/InstMerge/st_sink_two_stores.ll | 47 + test/Transforms/InstMerge/st_sink_with_barrier.ll | 42 + test/Transforms/InstSimplify/AndOrXor.ll | 55 + test/Transforms/InstSimplify/compare.ll | 64 + test/Transforms/InstSimplify/fast-math.ll | 9 + .../InstSimplify/floating-point-arithmetic.ll | 26 + .../InstSimplify/floating-point-compare.ll | 60 + test/Transforms/InstSimplify/load.ll | 19 + test/Transforms/InstSimplify/noalias-ptr.ll | 259 + test/Transforms/InstSimplify/select.ll | 161 + test/Transforms/InstSimplify/undef.ll | 105 + test/Transforms/JumpThreading/conservative-lvi.ll | 58 + test/Transforms/JumpThreading/phi-eq.ll | 2 +- test/Transforms/JumpThreading/pr22086.ll | 28 + test/Transforms/JumpThreading/thread-loads.ll | 8 +- test/Transforms/LCSSA/indirectbr.ll | 40 +- test/Transforms/LCSSA/unreachable-use.ll | 4 +- .../LICM/2011-04-06-PromoteResultOfPromotion.ll | 14 +- test/Transforms/LICM/constexpr.ll | 46 + test/Transforms/LICM/debug-value.ll | 56 +- test/Transforms/LICM/hoist-invariant-load.ll | 2 +- test/Transforms/LICM/preheader-safe.ll | 69 + test/Transforms/LICM/promote-order.ll | 10 +- test/Transforms/LICM/scalar_promote.ll | 12 +- test/Transforms/LICM/sinking.ll | 78 + test/Transforms/LoopIdiom/debug-line.ll | 44 +- test/Transforms/LoopReroll/basic.ll | 254 + test/Transforms/LoopReroll/reduction.ll | 36 + test/Transforms/LoopRotate/crash.ll | 18 + test/Transforms/LoopRotate/dbgvalue.ll | 52 +- test/Transforms/LoopRotate/pr22337.ll | 24 + .../LoopSimplify/2011-12-14-LandingpadHeader.ll | 2 +- .../LoopStrengthReduce/AArch64/lsr-memset.ll | 6 +- .../LoopStrengthReduce/ARM/ivchain-ARM.ll | 4 +- .../LoopStrengthReduce/X86/ivchain-X86.ll | 4 +- .../Transforms/LoopStrengthReduce/count-to-zero.ll | 2 +- test/Transforms/LoopStrengthReduce/pr12018.ll | 4 +- test/Transforms/LoopStrengthReduce/pr18165.ll | 18 +- test/Transforms/LoopStrengthReduce/uglygep.ll | 2 +- test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll | 99 + .../LoopUnroll/full-unroll-heuristics.ll | 62 + .../LoopUnroll/partial-unroll-optsize.ll | 19 +- test/Transforms/LoopUnroll/runtime-loop.ll | 8 +- test/Transforms/LoopUnroll/runtime-loop1.ll | 2 +- test/Transforms/LoopUnroll/runtime-loop2.ll | 2 +- test/Transforms/LoopUnroll/tripcount-overflow.ll | 29 +- .../LoopUnroll/unroll-pragmas-disabled.ll | 42 +- test/Transforms/LoopUnroll/unroll-pragmas.ll | 26 +- .../AArch64/arbitrary-induction-step.ll | 150 + .../LoopVectorize/PowerPC/small-loop-rdx.ll | 47 + .../LoopVectorize/X86/already-vectorized.ll | 8 +- .../X86/illegal-parallel-loop-uniform-write.ll | 6 +- .../LoopVectorize/X86/masked_load_store.ll | 502 + .../LoopVectorize/X86/metadata-enable.ll | 8 +- .../X86/parallel-loops-after-reg2mem.ll | 2 +- .../Transforms/LoopVectorize/X86/parallel-loops.ll | 10 +- test/Transforms/LoopVectorize/X86/small-size.ll | 2 +- .../Transforms/LoopVectorize/X86/vect.omp.force.ll | 6 +- .../LoopVectorize/X86/vect.omp.force.small-tc.ll | 6 +- .../LoopVectorize/X86/vector-scalar-select-cost.ll | 4 +- .../X86/vectorization-remarks-missed.ll | 74 +- .../LoopVectorize/X86/vectorization-remarks.ll | 46 +- .../LoopVectorize/conditional-assignment.ll | 40 +- test/Transforms/LoopVectorize/control-flow.ll | 42 +- test/Transforms/LoopVectorize/dbg.value.ll | 50 +- test/Transforms/LoopVectorize/debugloc.ll | 60 +- .../LoopVectorize/duplicated-metadata.ll | 6 +- test/Transforms/LoopVectorize/gcc-examples.ll | 3 +- .../LoopVectorize/if-conversion-edgemasks.ll | 5 +- test/Transforms/LoopVectorize/if-conversion.ll | 4 +- .../Transforms/LoopVectorize/incorrect-dom-info.ll | 2 +- test/Transforms/LoopVectorize/loop-form.ll | 31 + test/Transforms/LoopVectorize/loop-vect-memdep.ll | 26 + test/Transforms/LoopVectorize/metadata-unroll.ll | 4 +- test/Transforms/LoopVectorize/metadata-width.ll | 4 +- test/Transforms/LoopVectorize/metadata.ll | 20 +- test/Transforms/LoopVectorize/minmax_reduction.ll | 16 +- test/Transforms/LoopVectorize/no_array_bounds.ll | 54 +- test/Transforms/LoopVectorize/no_switch.ll | 50 +- test/Transforms/LoopVectorize/reverse_induction.ll | 4 +- .../LoopVectorize/runtime-check-address-space.ll | 154 +- .../runtime-check-readonly-address-space.ll | 120 +- .../Transforms/LoopVectorize/scev-exitlim-crash.ll | 12 +- test/Transforms/LoopVectorize/tbaa-nodep.ll | 12 +- .../LoopVectorize/vect.omp.persistence.ll | 8 +- test/Transforms/LoopVectorize/vect.stats.ll | 58 +- test/Transforms/LoopVectorize/vectorize-once.ll | 12 +- .../Transforms/LoopVectorize/version-mem-access.ll | 12 +- test/Transforms/LowerBitSets/constant.ll | 34 + test/Transforms/LowerBitSets/layout.ll | 35 + test/Transforms/LowerBitSets/simple.ll | 122 + test/Transforms/LowerBitSets/single-offset.ll | 40 + test/Transforms/LowerExpectIntrinsic/basic.ll | 9 +- .../2014-06-11-SwitchDefaultUnreachableOpt.ll | 7 +- .../fold-popular-case-to-unreachable-default.ll | 110 + test/Transforms/Mem2Reg/ConvertDebugInfo.ll | 38 +- test/Transforms/Mem2Reg/ConvertDebugInfo2.ll | 54 +- test/Transforms/MemCpyOpt/callslot_aa.ll | 22 + test/Transforms/MemCpyOpt/form-memset.ll | 15 + .../MergeFunc/call-and-invoke-with-ranges.ll | 4 +- test/Transforms/MergeFunc/ranges.ll | 4 +- test/Transforms/ObjCARC/allocas.ll | 2 +- test/Transforms/ObjCARC/arc-annotations.ll | 12 +- test/Transforms/ObjCARC/basic.ll | 10 +- test/Transforms/ObjCARC/cfg-hazards.ll | 2 +- test/Transforms/ObjCARC/contract-marker.ll | 2 +- test/Transforms/ObjCARC/contract-storestrong.ll | 98 +- test/Transforms/ObjCARC/contract-testcases.ll | 2 +- test/Transforms/ObjCARC/empty-block.ll | 2 +- ...ensure-that-exception-unwind-path-is-visited.ll | 126 +- test/Transforms/ObjCARC/escape.ll | 2 +- test/Transforms/ObjCARC/intrinsic-use.ll | 2 +- test/Transforms/ObjCARC/invoke.ll | 2 +- test/Transforms/ObjCARC/nested.ll | 2 +- test/Transforms/ObjCARC/path-overflow.ll | 2 +- test/Transforms/ObjCARC/retain-not-declared.ll | 2 +- test/Transforms/ObjCARC/split-backedge.ll | 2 +- test/Transforms/ObjCARC/weak-copies.ll | 2 +- test/Transforms/PlaceSafepoints/basic.ll | 94 + test/Transforms/PlaceSafepoints/call-in-loop.ll | 31 + test/Transforms/PlaceSafepoints/finite-loops.ll | 80 + test/Transforms/PlaceSafepoints/invokes.ll | 110 + test/Transforms/PlaceSafepoints/split-backedge.ll | 46 + test/Transforms/PruneEH/2003-11-21-PHIUpdate.ll | 15 - test/Transforms/PruneEH/recursivetest.ll | 5 + test/Transforms/PruneEH/seh-nounwind.ll | 31 + test/Transforms/PruneEH/simpletest.ll | 4 + test/Transforms/Reassociate/crash2.ll | 25 + test/Transforms/Reassociate/min_int.ll | 13 + test/Transforms/RewriteStatepointsForGC/basics.ll | 88 + test/Transforms/SLPVectorizer/X86/addsub.ll | 133 + test/Transforms/SLPVectorizer/X86/atomics.ll | 31 + test/Transforms/SLPVectorizer/X86/bad_types.ll | 50 + .../SLPVectorizer/X86/consecutive-access.ll | 2 +- test/Transforms/SLPVectorizer/X86/crash_cmpop.ll | 56 + .../SLPVectorizer/X86/crash_scheduling.ll | 4 +- test/Transforms/SLPVectorizer/X86/debug_info.ll | 74 +- test/Transforms/SLPVectorizer/X86/metadata.ll | 16 +- test/Transforms/SLPVectorizer/X86/operandorder.ll | 110 + test/Transforms/SLPVectorizer/X86/pr16899.ll | 12 +- test/Transforms/SROA/alignment.ll | 13 +- test/Transforms/SROA/basictest.ll | 155 + test/Transforms/SROA/vector-promotion.ll | 19 + test/Transforms/SampleProfile/branch.ll | 98 +- test/Transforms/SampleProfile/calls.ll | 52 +- test/Transforms/SampleProfile/discriminator.ll | 44 +- test/Transforms/SampleProfile/fnptr.ll | 52 +- test/Transforms/SampleProfile/propagate.ll | 86 +- test/Transforms/ScalarRepl/debuginfo-preserved.ll | 48 +- test/Transforms/Scalarizer/basic.ll | 12 +- test/Transforms/Scalarizer/dbginfo.ll | 66 +- .../SimplifyCFG/2007-11-22-InvokeNoUnwind.ll | 4 + .../SimplifyCFG/2008-01-02-hoist-fp-add.ll | 16 +- test/Transforms/SimplifyCFG/AArch64/lit.local.cfg | 5 + test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll | 72 + test/Transforms/SimplifyCFG/PhiBlockMerge.ll | 4 +- .../SimplifyCFG/PowerPC/cttz-ctlz-spec.ll | 45 + test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg | 2 + test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll | 249 + test/Transforms/SimplifyCFG/R600/lit.local.cfg | 2 + test/Transforms/SimplifyCFG/SpeculativeExec.ll | 16 - .../Transforms/SimplifyCFG/UnreachableEliminate.ll | 26 - .../SimplifyCFG/X86/speculate-cttz-ctlz.ll | 330 + .../SimplifyCFG/X86/switch_to_lookup_table.ll | 211 +- test/Transforms/SimplifyCFG/basictest.ll | 7 +- test/Transforms/SimplifyCFG/branch-fold-dbg.ll | 34 +- test/Transforms/SimplifyCFG/clamp.ll | 22 + test/Transforms/SimplifyCFG/hoist-dbgvalue.ll | 52 +- test/Transforms/SimplifyCFG/hoist-with-range.ll | 6 +- .../SimplifyCFG/preserve-branchweights-partial.ll | 2 +- .../preserve-branchweights-switch-create.ll | 18 +- .../SimplifyCFG/preserve-branchweights.ll | 48 +- test/Transforms/SimplifyCFG/seh-nounwind.ll | 31 + test/Transforms/SimplifyCFG/select-gep.ll | 23 +- test/Transforms/SimplifyCFG/sink-common-code.ll | 34 +- .../Transforms/SimplifyCFG/switch-range-to-icmp.ll | 77 + test/Transforms/SimplifyCFG/switch-to-br.ll | 64 + .../SimplifyCFG/switch-to-select-two-case.ll | 35 - test/Transforms/SimplifyCFG/trap-debugloc.ll | 22 +- test/Transforms/SimplifyCFG/trivial-throw.ll | 77 - test/Transforms/SimplifyCFG/volatile-phioper.ll | 2 +- test/Transforms/StraightLineStrengthReduce/slsr.ll | 119 + .../StripSymbols/2010-06-30-StripDebug.ll | 30 +- test/Transforms/StripSymbols/2010-08-25-crash.ll | 30 +- .../StripSymbols/strip-dead-debug-info.ll | 54 +- .../Transforms/StructurizeCFG/nested-loop-order.ll | 79 + .../StructurizeCFG/one-loop-multiple-backedges.ll | 42 + .../StructurizeCFG/post-order-traversal-bug.ll | 100 + .../Util/combine-alias-scope-metadata.ll | 24 + test/Transforms/Util/lowerswitch.ll | 36 +- test/Verifier/2008-03-01-AllocaSized.ll | 2 +- test/Verifier/comdat.ll | 2 +- test/Verifier/comdat2.ll | 2 +- test/Verifier/comdat3.ll | 5 + test/Verifier/fpmath.ll | 14 +- test/Verifier/frameallocate.ll | 48 + test/Verifier/ident-meta1.ll | 6 +- test/Verifier/ident-meta2.ll | 8 +- test/Verifier/ident-meta3.ll | 4 +- test/Verifier/ident-meta4.ll | 9 + test/Verifier/module-flags-1.ll | 47 +- test/Verifier/module-flags-2.ll | 6 + test/Verifier/module-flags-3.ll | 6 + test/Verifier/range-1.ll | 38 +- test/Verifier/range-2.ll | 10 +- test/Verifier/statepoint.ll | 83 + test/lit.cfg | 23 +- test/lit.site.cfg.in | 4 +- .../dsymutil/Inputs/basic-archive.macho.x86_64 | Bin 0 -> 9352 bytes test/tools/dsymutil/Inputs/basic-lto.macho.x86_64 | Bin 0 -> 8912 bytes .../tools/dsymutil/Inputs/basic-lto.macho.x86_64.o | Bin 0 -> 4516 bytes test/tools/dsymutil/Inputs/basic.macho.x86_64 | Bin 0 -> 9320 bytes test/tools/dsymutil/Inputs/basic1.c | 28 + test/tools/dsymutil/Inputs/basic1.macho.x86_64.o | Bin 0 -> 2376 bytes test/tools/dsymutil/Inputs/basic2.c | 22 + test/tools/dsymutil/Inputs/basic2.macho.x86_64.o | Bin 0 -> 3472 bytes test/tools/dsymutil/Inputs/basic3.c | 20 + test/tools/dsymutil/Inputs/basic3.macho.x86_64.o | Bin 0 -> 3008 bytes test/tools/dsymutil/Inputs/libbasic.a | Bin 0 -> 6840 bytes test/tools/dsymutil/basic-linking.test | 149 + test/tools/dsymutil/debug-map-parsing.test | 79 + test/tools/gold/Inputs/comdat.ll | 9 +- test/tools/gold/Inputs/drop-debug.bc | Bin 0 -> 1152 bytes test/tools/gold/alias.ll | 2 +- test/tools/gold/bad-alias.ll | 2 +- test/tools/gold/bcsection.ll | 2 +- test/tools/gold/coff.ll | 22 + test/tools/gold/comdat.ll | 14 +- test/tools/gold/common.ll | 6 +- test/tools/gold/drop-debug.ll | 8 + test/tools/gold/emit-llvm.ll | 26 +- test/tools/gold/invalid.ll | 2 +- test/tools/gold/linker-script.ll | 2 +- test/tools/gold/linkonce-weak.ll | 4 +- test/tools/gold/mtriple.ll | 2 +- test/tools/gold/no-map-whole-file.ll | 9 + test/tools/gold/option.ll | 2 +- test/tools/gold/pr19901.ll | 4 +- test/tools/gold/slp-vectorize.ll | 2 +- test/tools/gold/stats.ll | 7 + test/tools/gold/vectorize.ll | 2 +- test/tools/gold/weak.ll | 2 +- .../llvm-cov/Inputs/highlightedRanges.covmapping | Bin 355 -> 355 bytes .../tools/llvm-cov/Inputs/regionMarkers.covmapping | Bin 194 -> 202 bytes test/tools/llvm-cov/Inputs/report.covmapping | Bin 256 -> 219 bytes .../llvm-cov/Inputs/showExpansions.covmapping | Bin 194 -> 250 bytes test/tools/llvm-cov/report.cpp | 20 +- test/tools/llvm-cov/showHighlightedRanges.cpp | 12 +- test/tools/llvm-cov/showLineExecutionCounts.cpp | 4 +- .../AArch64/Inputs/link-opt-hints.macho-aarch64 | Bin 0 -> 984 bytes .../llvm-objdump/AArch64/macho-link-opt-hints.test | 11 + .../AArch64/macho-private-headers.test | 312 + .../llvm-objdump/ARM/Inputs/data-in-code.macho-arm | Bin 0 -> 336 bytes .../tools/llvm-objdump/ARM/macho-data-in-code.test | 8 + .../llvm-objdump/ARM/macho-private-headers.test | 345 + test/tools/llvm-objdump/Inputs/common-symbol-elf | Bin 0 -> 598 bytes .../llvm-objdump/Inputs/proc-specific-section-elf | Bin 0 -> 836 bytes .../X86/Inputs/dylibModInit.macho-x86_64 | Bin 0 -> 8256 bytes .../X86/Inputs/dylibRoutines.macho-x86_64 | Bin 0 -> 4288 bytes .../X86/Inputs/dylibSubClient.macho-x86_64 | Bin 0 -> 4240 bytes .../X86/Inputs/dylibSubFramework.macho-x86_64 | Bin 0 -> 4240 bytes .../X86/Inputs/dylibSubLibrary.macho-x86_64 | Bin 0 -> 4220 bytes .../X86/Inputs/dylibSubUmbrella.macho-x86_64 | Bin 0 -> 4220 bytes .../llvm-objdump/X86/Inputs/exeThread.macho-x86_64 | Bin 0 -> 9100 bytes .../X86/Inputs/linkerOption.macho-x86_64 | Bin 0 -> 744 bytes .../X86/Inputs/macho-universal-archive.x86_64.i386 | Bin 0 -> 1656 bytes .../X86/Inputs/macho-universal.x86_64.i386 | Bin 0 -> 16624 bytes .../llvm-objdump/X86/macho-archive-headers.test | 10 + .../tools/llvm-objdump/X86/macho-cstring-dump.test | 4 + .../llvm-objdump/X86/macho-indirect-symbols.test | 12 + .../X86/macho-literal-pointers-i386.test | 34 + .../X86/macho-literal-pointers-x86_64.test | 34 + test/tools/llvm-objdump/X86/macho-literals.test | 48 + .../llvm-objdump/X86/macho-nontext-disasm.test | 9 + .../llvm-objdump/X86/macho-private-headers.test | 77 + test/tools/llvm-objdump/X86/macho-relocations.test | 7 + .../llvm-objdump/X86/macho-section-contents.test | 17 + .../llvm-objdump/X86/macho-section-headers.test | 8 + test/tools/llvm-objdump/X86/macho-section.test | 4 + .../tools/llvm-objdump/X86/macho-symbol-table.test | 8 + .../X86/macho-universal-x86_64.i386.test | 44 + test/tools/llvm-objdump/X86/macho-unwind-info.test | 7 + test/tools/llvm-objdump/common-symbol-elf.test | 3 + .../llvm-objdump/proc-specific-section-elf.test | 3 + test/tools/llvm-readobj/ARM/attribute-0.s | 234 + test/tools/llvm-readobj/ARM/attribute-1.s | 220 + test/tools/llvm-readobj/ARM/attribute-10.s | 24 + test/tools/llvm-readobj/ARM/attribute-11.s | 24 + test/tools/llvm-readobj/ARM/attribute-12.s | 24 + test/tools/llvm-readobj/ARM/attribute-13.s | 10 + test/tools/llvm-readobj/ARM/attribute-136.s | 10 + test/tools/llvm-readobj/ARM/attribute-14.s | 10 + test/tools/llvm-readobj/ARM/attribute-15.s | 10 + test/tools/llvm-readobj/ARM/attribute-2.s | 178 + test/tools/llvm-readobj/ARM/attribute-3.s | 108 + test/tools/llvm-readobj/ARM/attribute-4.s | 59 + test/tools/llvm-readobj/ARM/attribute-5.s | 52 + test/tools/llvm-readobj/ARM/attribute-6.s | 52 + test/tools/llvm-readobj/ARM/attribute-7.s | 38 + test/tools/llvm-readobj/ARM/attribute-8.s | 31 + test/tools/llvm-readobj/ARM/attribute-9.s | 24 + test/tools/llvm-readobj/ARM/attribute-A.s | 10 + test/tools/llvm-readobj/ARM/attribute-M.s | 10 + test/tools/llvm-readobj/ARM/attribute-R.s | 10 + test/tools/llvm-readobj/ARM/attribute-S.s | 10 + .../llvm-readobj/ARM/attribute-conformance-1.s | 8 + .../llvm-readobj/ARM/attribute-conformance-2.s | 8 + test/tools/llvm-readobj/ARM/attributes.s | 287 - test/tools/llvm-readobj/Inputs/export-arm.dll | Bin 0 -> 5632 bytes test/tools/llvm-readobj/Inputs/export-x64.dll | Bin 0 -> 6144 bytes test/tools/llvm-readobj/Inputs/export-x86.dll | Bin 0 -> 6144 bytes .../Inputs/relocs-no-symtab.obj.coff-i386 | Bin 0 -> 97 bytes .../llvm-readobj/Inputs/relocs.obj.elf-aarch64 | Bin 3144 -> 4232 bytes test/tools/llvm-readobj/Inputs/relocs.obj.elf-arm | Bin 2100 -> 2112 bytes test/tools/llvm-readobj/Inputs/relocs.py | 44 +- .../tools/llvm-readobj/Inputs/trivial.exe.coff-arm | Bin 0 -> 7680 bytes test/tools/llvm-readobj/codeview-linetables.test | 28 +- test/tools/llvm-readobj/coff-arm-baserelocs.test | 7 + test/tools/llvm-readobj/coff-exports.test | 11 + test/tools/llvm-readobj/reloc-types.test | 44 +- test/tools/llvm-readobj/relocations.test | 2 + tools/CMakeLists.txt | 16 +- tools/LLVMBuild.txt | 2 +- tools/Makefile | 2 +- tools/bugpoint/CrashDebugger.cpp | 4 +- tools/bugpoint/ExtractFunction.cpp | 6 +- tools/bugpoint/OptimizerDriver.cpp | 2 +- tools/bugpoint/bugpoint.cpp | 4 +- tools/dsymutil/BinaryHolder.cpp | 111 + tools/dsymutil/BinaryHolder.h | 104 + tools/dsymutil/CMakeLists.txt | 14 + tools/dsymutil/DebugMap.cpp | 92 + tools/dsymutil/DebugMap.h | 142 + tools/dsymutil/DwarfLinker.cpp | 667 + tools/dsymutil/LLVMBuild.txt | 22 + tools/dsymutil/MachODebugMapParser.cpp | 241 + tools/dsymutil/Makefile | 17 + tools/dsymutil/dsymutil.cpp | 71 + tools/dsymutil/dsymutil.h | 39 + tools/gold/CMakeLists.txt | 9 +- tools/gold/gold-plugin.cpp | 275 +- tools/llc/CMakeLists.txt | 2 +- tools/llc/llc.cpp | 53 +- tools/lli/Android.mk | 3 +- tools/lli/CMakeLists.txt | 4 +- tools/lli/ChildTarget/ChildTarget.cpp | 14 +- tools/lli/Makefile | 4 +- tools/lli/RemoteMemoryManager.cpp | 3 +- tools/lli/RemoteMemoryManager.h | 3 +- tools/lli/lli.cpp | 26 +- tools/llvm-ar/CMakeLists.txt | 15 +- tools/llvm-ar/install_symlink.cmake | 25 + tools/llvm-ar/llvm-ar.cpp | 68 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 14 +- tools/llvm-c-test/Android.mk | 1 + tools/llvm-c-test/CMakeLists.txt | 25 +- tools/llvm-c-test/llvm-c-test.h | 4 + tools/llvm-c-test/main.c | 4 + tools/llvm-c-test/metadata.c | 43 + tools/llvm-config/BuildVariables.inc.in | 1 + tools/llvm-config/Makefile | 2 + tools/llvm-config/llvm-config.cpp | 10 +- tools/llvm-cov/Android.mk | 1 - tools/llvm-cov/CMakeLists.txt | 1 - tools/llvm-cov/CodeCoverage.cpp | 36 +- tools/llvm-cov/CoverageFilters.h | 2 +- tools/llvm-cov/CoverageReport.cpp | 42 +- tools/llvm-cov/CoverageReport.h | 11 +- tools/llvm-cov/CoverageSummary.cpp | 64 - tools/llvm-cov/CoverageSummary.h | 45 - tools/llvm-cov/CoverageSummaryInfo.cpp | 25 - tools/llvm-cov/CoverageSummaryInfo.h | 53 +- tools/llvm-cov/RenderingSupport.h | 2 +- tools/llvm-cov/SourceCoverageView.h | 7 +- tools/llvm-cov/TestingSupport.cpp | 9 +- tools/llvm-cov/gcov.cpp | 3 +- tools/llvm-cov/llvm-cov.cpp | 2 +- tools/llvm-dis/llvm-dis.cpp | 46 +- tools/llvm-dwarfdump/Android.mk | 3 +- tools/llvm-dwarfdump/CMakeLists.txt | 2 +- tools/llvm-dwarfdump/LLVMBuild.txt | 2 +- tools/llvm-dwarfdump/Makefile | 2 +- tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 3 +- tools/llvm-extract/llvm-extract.cpp | 4 +- tools/llvm-go/llvm-go.go | 30 +- tools/llvm-jitlistener/Makefile | 2 +- tools/llvm-jitlistener/llvm-jitlistener.cpp | 6 +- tools/llvm-lto/llvm-lto.cpp | 69 +- tools/llvm-mc/Android.mk | 1 + tools/llvm-mc/Disassembler.cpp | 1 - tools/llvm-mc/llvm-mc.cpp | 103 +- tools/llvm-nm/Android.mk | 1 + tools/llvm-nm/llvm-nm.cpp | 16 +- tools/llvm-objdump/Android.mk | 4 +- tools/llvm-objdump/CMakeLists.txt | 2 +- tools/llvm-objdump/LLVMBuild.txt | 2 +- tools/llvm-objdump/MachODump.cpp | 2098 +- tools/llvm-objdump/Makefile | 2 +- tools/llvm-objdump/llvm-objdump.cpp | 104 +- tools/llvm-objdump/llvm-objdump.h | 29 +- tools/llvm-pdbdump/CMakeLists.txt | 14 + tools/llvm-pdbdump/ClassDefinitionDumper.cpp | 152 + tools/llvm-pdbdump/ClassDefinitionDumper.h | 64 + tools/llvm-pdbdump/CompilandDumper.cpp | 117 + tools/llvm-pdbdump/CompilandDumper.h | 39 + tools/llvm-pdbdump/FunctionDumper.cpp | 243 + tools/llvm-pdbdump/FunctionDumper.h | 45 + tools/llvm-pdbdump/LLVMBuild.txt | 23 + tools/llvm-pdbdump/Makefile | 17 + tools/llvm-pdbdump/TypeDumper.cpp | 96 + tools/llvm-pdbdump/TypeDumper.h | 38 + tools/llvm-pdbdump/TypedefDumper.cpp | 84 + tools/llvm-pdbdump/TypedefDumper.h | 38 + tools/llvm-pdbdump/VariableDumper.cpp | 120 + tools/llvm-pdbdump/VariableDumper.h | 43 + tools/llvm-pdbdump/llvm-pdbdump.cpp | 134 + tools/llvm-pdbdump/llvm-pdbdump.h | 28 + tools/llvm-profdata/llvm-profdata.cpp | 8 +- tools/llvm-readobj/ARMAttributeParser.cpp | 2 +- tools/llvm-readobj/ARMWinEHPrinter.cpp | 2 +- tools/llvm-readobj/COFFDumper.cpp | 55 +- tools/llvm-readobj/ELFDumper.cpp | 7 +- tools/llvm-readobj/ObjDumper.h | 1 + tools/llvm-readobj/llvm-readobj.cpp | 17 +- tools/llvm-readobj/llvm-readobj.h | 3 +- tools/llvm-rtdyld/Android.mk | 3 +- tools/llvm-rtdyld/CMakeLists.txt | 3 +- tools/llvm-rtdyld/Makefile | 2 +- tools/llvm-rtdyld/llvm-rtdyld.cpp | 62 +- tools/llvm-shlib/CMakeLists.txt | 6 +- tools/llvm-shlib/libllvm.cpp | 7 + tools/llvm-size/llvm-size.cpp | 19 +- tools/llvm-stress/llvm-stress.cpp | 4 +- tools/llvm-symbolizer/Android.mk | 3 +- tools/llvm-symbolizer/CMakeLists.txt | 2 +- tools/llvm-symbolizer/LLVMSymbolize.h | 2 +- tools/llvm-symbolizer/Makefile | 2 +- tools/lto/CMakeLists.txt | 1 + tools/lto/lto.cpp | 48 +- tools/lto/lto.exports | 7 + tools/macho-dump/macho-dump.cpp | 8 +- tools/obj2yaml/elf2yaml.cpp | 46 +- tools/opt/NewPMDriver.cpp | 40 +- tools/opt/NewPMDriver.h | 6 +- tools/opt/PassRegistry.def | 26 + tools/opt/Passes.cpp | 236 +- tools/opt/Passes.h | 114 +- tools/opt/opt.cpp | 67 +- tools/verify-uselistorder/verify-uselistorder.cpp | 10 +- tools/yaml2obj/yaml2coff.cpp | 4 +- tools/yaml2obj/yaml2elf.cpp | 54 +- unittests/ADT/APFloatTest.cpp | 41 + unittests/ADT/APIntTest.cpp | 13 +- unittests/ADT/APSIntTest.cpp | 102 + unittests/ADT/ArrayRefTest.cpp | 21 + unittests/ADT/HashingTest.cpp | 25 + unittests/ADT/MapVectorTest.cpp | 218 + unittests/ADT/OptionalTest.cpp | 10 +- unittests/ADT/PointerIntPairTest.cpp | 2 - unittests/ADT/SmallVectorTest.cpp | 223 +- unittests/ADT/StringMapTest.cpp | 8 +- unittests/ADT/TinyPtrVectorTest.cpp | 47 + unittests/ADT/TripleTest.cpp | 17 + unittests/Analysis/CFGTest.cpp | 10 +- unittests/Analysis/MixedTBAATest.cpp | 4 +- unittests/Analysis/ScalarEvolutionTest.cpp | 4 +- unittests/Bitcode/BitReaderTest.cpp | 2 +- unittests/CMakeLists.txt | 3 +- unittests/CodeGen/DIEHashTest.cpp | 4 +- unittests/DebugInfo/CMakeLists.txt | 12 +- unittests/DebugInfo/DWARF/CMakeLists.txt | 11 + unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp | 49 + unittests/DebugInfo/DWARF/Makefile | 16 + unittests/DebugInfo/DWARFFormValueTest.cpp | 49 - unittests/DebugInfo/Makefile | 5 +- unittests/DebugInfo/PDB/CMakeLists.txt | 11 + unittests/DebugInfo/PDB/Makefile | 16 + unittests/DebugInfo/PDB/PDBApiTest.cpp | 387 + unittests/ExecutionEngine/CMakeLists.txt | 4 + unittests/ExecutionEngine/MCJIT/CMakeLists.txt | 1 + unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 32 + .../MCJIT/MCJITMultipleModuleTest.cpp | 19 + .../ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp | 4 +- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h | 4 +- unittests/ExecutionEngine/Makefile | 4 +- unittests/ExecutionEngine/Orc/CMakeLists.txt | 8 + .../ExecutionEngine/Orc/LazyEmittingLayerTest.cpp | 30 + unittests/ExecutionEngine/Orc/Makefile | 16 + unittests/IR/CMakeLists.txt | 1 - unittests/IR/ConstantsTest.cpp | 16 + unittests/IR/DebugInfoTest.cpp | 67 + unittests/IR/DominatorTreeTest.cpp | 4 +- unittests/IR/IRBuilderTest.cpp | 18 + unittests/IR/LeakDetectorTest.cpp | 31 - unittests/IR/LegacyPassManagerTest.cpp | 19 +- unittests/IR/MDBuilderTest.cpp | 21 +- unittests/IR/MetadataTest.cpp | 1773 +- unittests/IR/PassManagerTest.cpp | 35 +- unittests/IR/UseTest.cpp | 10 +- unittests/IR/UserTest.cpp | 2 +- unittests/IR/WaymarkTest.cpp | 5 +- unittests/Linker/LinkModulesTest.cpp | 2 +- unittests/MC/CMakeLists.txt | 6 - unittests/MC/Hexagon/CMakeLists.txt | 14 - unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp | 53 - unittests/MC/StringTableBuilderTest.cpp | 2 +- unittests/Makefile | 2 +- unittests/ProfileData/CMakeLists.txt | 10 + unittests/ProfileData/CoverageMappingTest.cpp | 262 + unittests/ProfileData/InstrProfTest.cpp | 98 + unittests/ProfileData/Makefile | 15 + unittests/Support/AlignOfTest.cpp | 8 +- unittests/Support/BlockFrequencyTest.cpp | 9 + unittests/Support/CMakeLists.txt | 3 + unittests/Support/Casting.cpp | 96 + unittests/Support/CommandLineTest.cpp | 47 +- unittests/Support/CompressionTest.cpp | 2 +- unittests/Support/ConvertUTFTest.cpp | 18 +- unittests/Support/DwarfTest.cpp | 141 + unittests/Support/EndianStreamTest.cpp | 157 + unittests/Support/FileOutputBufferTest.cpp | 7 +- unittests/Support/MathExtrasTest.cpp | 11 +- unittests/Support/MemoryTest.cpp | 2 +- unittests/Support/Path.cpp | 41 +- unittests/Support/ProcessTest.cpp | 20 - unittests/Support/ProgramTest.cpp | 50 + unittests/Support/ScaledNumberTest.cpp | 1 - unittests/Support/SpecialCaseListTest.cpp | 38 +- unittests/Support/StreamingMemoryObject.cpp | 29 + unittests/Support/StringPool.cpp | 4 +- unittests/Support/ThreadLocalTest.cpp | 23 +- unittests/Support/raw_ostream_test.cpp | 2 + unittests/Transforms/CMakeLists.txt | 2 +- unittests/Transforms/DebugIR/CMakeLists.txt | 9 - unittests/Transforms/DebugIR/DebugIR.cpp | 308 - unittests/Transforms/DebugIR/Makefile | 15 - unittests/Transforms/IPO/CMakeLists.txt | 9 + unittests/Transforms/IPO/LowerBitSets.cpp | 95 + unittests/Transforms/IPO/Makefile | 15 + unittests/Transforms/Makefile | 2 +- unittests/Transforms/Utils/Cloning.cpp | 5 +- utils/FileCheck/FileCheck.cpp | 49 +- utils/TableGen/AsmMatcherEmitter.cpp | 429 +- utils/TableGen/AsmWriterEmitter.cpp | 84 +- utils/TableGen/AsmWriterInst.cpp | 4 +- utils/TableGen/AsmWriterInst.h | 3 +- utils/TableGen/CallingConvEmitter.cpp | 11 +- utils/TableGen/CodeEmitterGen.cpp | 2 +- utils/TableGen/CodeGenDAGPatterns.cpp | 60 +- utils/TableGen/CodeGenInstruction.cpp | 14 +- utils/TableGen/CodeGenInstruction.h | 2 +- utils/TableGen/CodeGenMapTable.cpp | 4 +- utils/TableGen/CodeGenRegisters.cpp | 618 +- utils/TableGen/CodeGenRegisters.h | 143 +- utils/TableGen/CodeGenSchedule.cpp | 44 +- utils/TableGen/CodeGenTarget.cpp | 52 +- utils/TableGen/CodeGenTarget.h | 13 +- utils/TableGen/DAGISelEmitter.cpp | 8 +- utils/TableGen/DAGISelMatcher.h | 3 +- utils/TableGen/DAGISelMatcherGen.cpp | 4 +- utils/TableGen/DAGISelMatcherOpt.cpp | 7 +- utils/TableGen/DFAPacketizerEmitter.cpp | 2 +- utils/TableGen/FixedLenDecoderEmitter.cpp | 97 +- utils/TableGen/InstrInfoEmitter.cpp | 10 +- utils/TableGen/IntrinsicEmitter.cpp | 29 +- utils/TableGen/RegisterInfoEmitter.cpp | 553 +- utils/TableGen/SequenceToOffsetTable.h | 5 + utils/TableGen/SubtargetEmitter.cpp | 2 +- utils/TableGen/TableGen.cpp | 16 +- utils/TableGen/X86DisassemblerTables.cpp | 49 +- utils/TableGen/X86DisassemblerTables.h | 4 +- utils/TableGen/X86RecognizableInstr.cpp | 195 +- utils/TableGen/X86RecognizableInstr.h | 4 +- utils/emacs/emacs.el | 37 +- utils/emacs/llvm-mode.el | 111 +- utils/emacs/tablegen-mode.el | 20 +- utils/lit/lit/LitConfig.py | 2 - utils/lit/lit/Test.py | 5 +- utils/lit/lit/TestingConfig.py | 6 +- utils/lit/lit/formats/googletest.py | 1 - utils/lit/lit/util.py | 18 +- utils/lit/utils/check-coverage | 2 +- utils/lldbDataFormatters.py | 10 + utils/not/not.cpp | 5 + utils/release/merge.sh | 10 +- utils/release/tag.sh | 39 +- utils/release/test-release.sh | 48 +- utils/shuffle_fuzz.py | 5 +- utils/unittest/CMakeLists.txt | 17 +- utils/update_llc_test_checks.py | 213 + utils/vim/llvm.vim | 46 +- 4994 files changed, 295211 insertions(+), 130095 deletions(-) create mode 100644 bindings/ocaml/CMakeLists.txt create mode 100644 bindings/ocaml/all_backends/CMakeLists.txt create mode 100644 bindings/ocaml/analysis/CMakeLists.txt create mode 100644 bindings/ocaml/backends/CMakeLists.txt create mode 100644 bindings/ocaml/bitreader/CMakeLists.txt create mode 100644 bindings/ocaml/bitwriter/CMakeLists.txt create mode 100644 bindings/ocaml/executionengine/CMakeLists.txt create mode 100644 bindings/ocaml/irreader/CMakeLists.txt create mode 100644 bindings/ocaml/linker/CMakeLists.txt create mode 100644 bindings/ocaml/llvm/CMakeLists.txt create mode 100644 bindings/ocaml/target/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/ipo/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/scalar_opts/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/utils/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/utils/Makefile create mode 100644 bindings/ocaml/transforms/utils/llvm_transform_utils.ml create mode 100644 bindings/ocaml/transforms/utils/llvm_transform_utils.mli create mode 100644 bindings/ocaml/transforms/utils/transform_utils_ocaml.c create mode 100644 bindings/ocaml/transforms/vectorize/CMakeLists.txt create mode 100644 cmake/modules/AddOCaml.cmake create mode 100644 cmake/modules/FindOCaml.cmake create mode 100644 docs/BitSets.rst create mode 100644 docs/MergeFunctions.rst create mode 100644 docs/Statepoints.rst create mode 100644 docs/tutorial/LangImpl9.rst create mode 100644 examples/Kaleidoscope/Chapter8/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Chapter8/Makefile create mode 100644 examples/Kaleidoscope/Chapter8/toy.cpp create mode 100644 examples/Kaleidoscope/Orc/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Orc/fully_lazy/Makefile create mode 100644 examples/Kaleidoscope/Orc/fully_lazy/README.txt create mode 100644 examples/Kaleidoscope/Orc/fully_lazy/toy.cpp create mode 100644 examples/Kaleidoscope/Orc/initial/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Orc/initial/Makefile create mode 100644 examples/Kaleidoscope/Orc/initial/README.txt create mode 100644 examples/Kaleidoscope/Orc/initial/toy.cpp create mode 100644 examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Orc/lazy_codegen/Makefile create mode 100644 examples/Kaleidoscope/Orc/lazy_codegen/README.txt create mode 100644 examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp create mode 100644 examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Orc/lazy_irgen/Makefile create mode 100644 examples/Kaleidoscope/Orc/lazy_irgen/README.txt create mode 100644 examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp create mode 100644 include/llvm/Analysis/AssumptionCache.h delete mode 100644 include/llvm/Analysis/AssumptionTracker.h delete mode 100644 include/llvm/Analysis/FindUsedTypes.h delete mode 100644 include/llvm/Analysis/FunctionTargetTransformInfo.h create mode 100644 include/llvm/Analysis/LoopAccessAnalysis.h create mode 100644 include/llvm/Analysis/TargetLibraryInfo.h create mode 100644 include/llvm/Analysis/TargetTransformInfoImpl.h create mode 100644 include/llvm/CodeGen/BasicTTIImpl.h create mode 100644 include/llvm/CodeGen/DIE.h delete mode 100644 include/llvm/DebugInfo/DIContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DIContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugLine.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFFormValue.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFRelocMap.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFSection.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFUnit.h delete mode 100644 include/llvm/DebugInfo/DWARFFormValue.h create mode 100644 include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIADataStream.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASession.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASupport.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBDataStream.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBEnumChildren.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBLineNumber.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBRawSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBSession.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBSourceFile.h create mode 100644 include/llvm/DebugInfo/PDB/PDB.h create mode 100644 include/llvm/DebugInfo/PDB/PDBExtras.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymDumper.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolBlock.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCustom.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolData.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolExe.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFunc.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolLabel.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolThunk.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h create mode 100644 include/llvm/DebugInfo/PDB/PDBTypes.h delete mode 100644 include/llvm/ExecutionEngine/ObjectBuffer.h delete mode 100644 include/llvm/ExecutionEngine/ObjectImage.h create mode 100644 include/llvm/ExecutionEngine/ObjectMemoryBuffer.h create mode 100644 include/llvm/ExecutionEngine/Orc/CloneSubModule.h create mode 100644 include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/CompileUtils.h create mode 100644 include/llvm/ExecutionEngine/Orc/IRCompileLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/IndirectionUtils.h create mode 100644 include/llvm/ExecutionEngine/Orc/JITSymbol.h create mode 100644 include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h create mode 100644 include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h create mode 100644 include/llvm/ExecutionEngine/OrcMCJITReplacement.h create mode 100644 include/llvm/IR/DebugInfoFlags.def create mode 100644 include/llvm/IR/DebugInfoMetadata.h create mode 100644 include/llvm/IR/IntrinsicsBPF.td delete mode 100644 include/llvm/IR/LeakDetector.h create mode 100644 include/llvm/IR/Metadata.def create mode 100644 include/llvm/IR/MetadataTracking.h create mode 100644 include/llvm/IR/PassManagerInternal.h create mode 100644 include/llvm/IR/Statepoint.h create mode 100644 include/llvm/IR/TrackingMDRef.h delete mode 100644 include/llvm/PassManager.h create mode 100644 include/llvm/Support/Dwarf.def create mode 100644 include/llvm/Support/ELFRelocs/AArch64.def create mode 100644 include/llvm/Support/ELFRelocs/ARM.def create mode 100644 include/llvm/Support/ELFRelocs/Hexagon.def create mode 100644 include/llvm/Support/ELFRelocs/Mips.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC64.def create mode 100644 include/llvm/Support/ELFRelocs/Sparc.def create mode 100644 include/llvm/Support/ELFRelocs/SystemZ.def create mode 100644 include/llvm/Support/ELFRelocs/i386.def create mode 100644 include/llvm/Support/ELFRelocs/x86_64.def delete mode 100644 include/llvm/Target/TargetLibraryInfo.h create mode 100644 include/llvm/Transforms/IPO/LowerBitSets.h create mode 100644 include/llvm/Transforms/InstCombine/InstCombine.h create mode 100644 include/llvm/Transforms/InstCombine/InstCombineWorklist.h create mode 100644 include/llvm/Transforms/Scalar/EarlyCSE.h create mode 100644 include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h create mode 100644 include/llvm/Transforms/Scalar/SimplifyCFG.h create mode 100644 lib/Analysis/AssumptionCache.cpp delete mode 100644 lib/Analysis/AssumptionTracker.cpp delete mode 100644 lib/Analysis/FunctionTargetTransformInfo.cpp delete mode 100644 lib/Analysis/IPA/FindUsedTypes.cpp create mode 100644 lib/Analysis/LoopAccessAnalysis.cpp create mode 100644 lib/Analysis/MemDerefPrinter.cpp create mode 100644 lib/Analysis/TargetLibraryInfo.cpp delete mode 100644 lib/CodeGen/AsmPrinter/DIE.h create mode 100644 lib/CodeGen/AsmPrinter/DwarfExpression.cpp create mode 100644 lib/CodeGen/AsmPrinter/DwarfExpression.h create mode 100644 lib/CodeGen/GCRootLowering.cpp create mode 100644 lib/CodeGen/SelectionDAG/StatepointLowering.cpp create mode 100644 lib/CodeGen/SelectionDAG/StatepointLowering.h create mode 100644 lib/CodeGen/ShadowStackGCLowering.cpp create mode 100644 lib/CodeGen/StatepointExampleGC.cpp create mode 100644 lib/CodeGen/WinEHPrepare.cpp delete mode 100644 lib/DebugInfo/Android.mk delete mode 100644 lib/DebugInfo/DIContext.cpp create mode 100644 lib/DebugInfo/DWARF/Android.mk create mode 100644 lib/DebugInfo/DWARF/CMakeLists.txt create mode 100644 lib/DebugInfo/DWARF/DIContext.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFCompileUnit.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFContext.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugAranges.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugFrame.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugLine.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugLoc.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFFormValue.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFTypeUnit.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFUnit.cpp create mode 100644 lib/DebugInfo/DWARF/LLVMBuild.txt create mode 100644 lib/DebugInfo/DWARF/Makefile create mode 100644 lib/DebugInfo/DWARF/SyntaxHighlighting.cpp create mode 100644 lib/DebugInfo/DWARF/SyntaxHighlighting.h create mode 100644 lib/DebugInfo/DWARF/module.modulemap delete mode 100644 lib/DebugInfo/DWARFAbbreviationDeclaration.cpp delete mode 100644 lib/DebugInfo/DWARFAbbreviationDeclaration.h delete mode 100644 lib/DebugInfo/DWARFAcceleratorTable.cpp delete mode 100644 lib/DebugInfo/DWARFAcceleratorTable.h delete mode 100644 lib/DebugInfo/DWARFCompileUnit.cpp delete mode 100644 lib/DebugInfo/DWARFCompileUnit.h delete mode 100644 lib/DebugInfo/DWARFContext.cpp delete mode 100644 lib/DebugInfo/DWARFContext.h delete mode 100644 lib/DebugInfo/DWARFDebugAbbrev.cpp delete mode 100644 lib/DebugInfo/DWARFDebugAbbrev.h delete mode 100644 lib/DebugInfo/DWARFDebugArangeSet.cpp delete mode 100644 lib/DebugInfo/DWARFDebugArangeSet.h delete mode 100644 lib/DebugInfo/DWARFDebugAranges.cpp delete mode 100644 lib/DebugInfo/DWARFDebugAranges.h delete mode 100644 lib/DebugInfo/DWARFDebugFrame.cpp delete mode 100644 lib/DebugInfo/DWARFDebugFrame.h delete mode 100644 lib/DebugInfo/DWARFDebugInfoEntry.cpp delete mode 100644 lib/DebugInfo/DWARFDebugInfoEntry.h delete mode 100644 lib/DebugInfo/DWARFDebugLine.cpp delete mode 100644 lib/DebugInfo/DWARFDebugLine.h delete mode 100644 lib/DebugInfo/DWARFDebugLoc.cpp delete mode 100644 lib/DebugInfo/DWARFDebugLoc.h delete mode 100644 lib/DebugInfo/DWARFDebugRangeList.cpp delete mode 100644 lib/DebugInfo/DWARFDebugRangeList.h delete mode 100644 lib/DebugInfo/DWARFFormValue.cpp delete mode 100644 lib/DebugInfo/DWARFRelocMap.h delete mode 100644 lib/DebugInfo/DWARFSection.h delete mode 100644 lib/DebugInfo/DWARFTypeUnit.cpp delete mode 100644 lib/DebugInfo/DWARFTypeUnit.h delete mode 100644 lib/DebugInfo/DWARFUnit.cpp delete mode 100644 lib/DebugInfo/DWARFUnit.h create mode 100644 lib/DebugInfo/PDB/Android.mk create mode 100644 lib/DebugInfo/PDB/CMakeLists.txt create mode 100644 lib/DebugInfo/PDB/DIA/DIADataStream.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIALineNumber.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIASession.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIASourceFile.cpp create mode 100644 lib/DebugInfo/PDB/IPDBSourceFile.cpp create mode 100644 lib/DebugInfo/PDB/LLVMBuild.txt create mode 100644 lib/DebugInfo/PDB/Makefile create mode 100644 lib/DebugInfo/PDB/PDB.cpp create mode 100644 lib/DebugInfo/PDB/PDBExtras.cpp create mode 100644 lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymDumper.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbol.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolBlock.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompiland.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCustom.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolData.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolExe.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFunc.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolLabel.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolThunk.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolUnknown.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp delete mode 100644 lib/DebugInfo/module.modulemap create mode 100644 lib/ExecutionEngine/GDBRegistrationListener.cpp delete mode 100644 lib/ExecutionEngine/JITEventListener.cpp create mode 100644 lib/ExecutionEngine/MCJIT/ObjectBuffer.h delete mode 100644 lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp create mode 100644 lib/ExecutionEngine/Orc/Android.mk create mode 100644 lib/ExecutionEngine/Orc/CMakeLists.txt create mode 100644 lib/ExecutionEngine/Orc/CloneSubModule.cpp create mode 100644 lib/ExecutionEngine/Orc/IndirectionUtils.cpp create mode 100644 lib/ExecutionEngine/Orc/LLVMBuild.txt create mode 100644 lib/ExecutionEngine/Orc/Makefile create mode 100644 lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp create mode 100644 lib/ExecutionEngine/Orc/OrcMCJITReplacement.h create mode 100644 lib/ExecutionEngine/Orc/OrcTargetSupport.cpp delete mode 100644 lib/ExecutionEngine/RTDyldMemoryManager.cpp delete mode 100644 lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp delete mode 100644 lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h delete mode 100644 lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h create mode 100644 lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp create mode 100644 lib/ExecutionEngine/SectionMemoryManager.cpp create mode 100644 lib/Fuzzer/CMakeLists.txt create mode 100644 lib/Fuzzer/FuzzerCrossOver.cpp create mode 100644 lib/Fuzzer/FuzzerDriver.cpp create mode 100644 lib/Fuzzer/FuzzerFlags.def create mode 100644 lib/Fuzzer/FuzzerIO.cpp create mode 100644 lib/Fuzzer/FuzzerInterface.h create mode 100644 lib/Fuzzer/FuzzerInternal.h create mode 100644 lib/Fuzzer/FuzzerLoop.cpp create mode 100644 lib/Fuzzer/FuzzerMain.cpp create mode 100644 lib/Fuzzer/FuzzerMutate.cpp create mode 100644 lib/Fuzzer/FuzzerSanitizerOptions.cpp create mode 100644 lib/Fuzzer/FuzzerUtil.cpp create mode 100644 lib/Fuzzer/README.txt create mode 100644 lib/Fuzzer/test/CMakeLists.txt create mode 100644 lib/Fuzzer/test/FourIndependentBranchesTest.cpp create mode 100644 lib/Fuzzer/test/FullCoverageSetTest.cpp create mode 100644 lib/Fuzzer/test/FuzzerUnittest.cpp create mode 100644 lib/Fuzzer/test/InfiniteTest.cpp create mode 100644 lib/Fuzzer/test/NullDerefTest.cpp create mode 100644 lib/Fuzzer/test/SimpleTest.cpp create mode 100644 lib/Fuzzer/test/TimeoutTest.cpp create mode 100644 lib/Fuzzer/test/fuzzer.test create mode 100644 lib/Fuzzer/test/lit.cfg create mode 100644 lib/Fuzzer/test/lit.site.cfg.in create mode 100644 lib/Fuzzer/test/unit/lit.cfg create mode 100644 lib/Fuzzer/test/unit/lit.site.cfg.in create mode 100644 lib/IR/DebugInfoMetadata.cpp delete mode 100644 lib/IR/LeakDetector.cpp delete mode 100644 lib/IR/LeaksContext.h create mode 100644 lib/IR/MetadataImpl.h create mode 100644 lib/IR/MetadataTracking.cpp create mode 100644 lib/IR/Statepoint.cpp create mode 100644 lib/Target/AArch64/AArch64CallingConvention.h create mode 100644 lib/Target/AArch64/AArch64TargetTransformInfo.h create mode 100644 lib/Target/ARM/ARMArchExtName.def create mode 100644 lib/Target/ARM/ARMArchExtName.h create mode 100644 lib/Target/ARM/ARMTargetTransformInfo.h create mode 100644 lib/Target/BPF/BPF.h create mode 100644 lib/Target/BPF/BPF.td create mode 100644 lib/Target/BPF/BPFAsmPrinter.cpp create mode 100644 lib/Target/BPF/BPFCallingConv.td create mode 100644 lib/Target/BPF/BPFFrameLowering.cpp create mode 100644 lib/Target/BPF/BPFFrameLowering.h create mode 100644 lib/Target/BPF/BPFISelDAGToDAG.cpp create mode 100644 lib/Target/BPF/BPFISelLowering.cpp create mode 100644 lib/Target/BPF/BPFISelLowering.h create mode 100644 lib/Target/BPF/BPFInstrFormats.td create mode 100644 lib/Target/BPF/BPFInstrInfo.cpp create mode 100644 lib/Target/BPF/BPFInstrInfo.h create mode 100644 lib/Target/BPF/BPFInstrInfo.td create mode 100644 lib/Target/BPF/BPFMCInstLower.cpp create mode 100644 lib/Target/BPF/BPFMCInstLower.h create mode 100644 lib/Target/BPF/BPFRegisterInfo.cpp create mode 100644 lib/Target/BPF/BPFRegisterInfo.h create mode 100644 lib/Target/BPF/BPFRegisterInfo.td create mode 100644 lib/Target/BPF/BPFSubtarget.cpp create mode 100644 lib/Target/BPF/BPFSubtarget.h create mode 100644 lib/Target/BPF/BPFTargetMachine.cpp create mode 100644 lib/Target/BPF/BPFTargetMachine.h create mode 100644 lib/Target/BPF/CMakeLists.txt create mode 100644 lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp create mode 100644 lib/Target/BPF/InstPrinter/BPFInstPrinter.h create mode 100644 lib/Target/BPF/InstPrinter/CMakeLists.txt create mode 100644 lib/Target/BPF/InstPrinter/LLVMBuild.txt create mode 100644 lib/Target/BPF/InstPrinter/Makefile create mode 100644 lib/Target/BPF/LLVMBuild.txt create mode 100644 lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp create mode 100644 lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp create mode 100644 lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h create mode 100644 lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp create mode 100644 lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp create mode 100644 lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h create mode 100644 lib/Target/BPF/MCTargetDesc/CMakeLists.txt create mode 100644 lib/Target/BPF/MCTargetDesc/LLVMBuild.txt create mode 100644 lib/Target/BPF/MCTargetDesc/Makefile create mode 100644 lib/Target/BPF/Makefile create mode 100644 lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp create mode 100644 lib/Target/BPF/TargetInfo/CMakeLists.txt create mode 100644 lib/Target/BPF/TargetInfo/LLVMBuild.txt create mode 100644 lib/Target/BPF/TargetInfo/Makefile delete mode 100644 lib/Target/Hexagon/HexagonCallingConvLower.cpp delete mode 100644 lib/Target/Hexagon/HexagonCallingConvLower.h create mode 100644 lib/Target/Hexagon/HexagonInstrInfoVector.td delete mode 100644 lib/Target/Hexagon/HexagonVarargsCallingConvention.h delete mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp delete mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h create mode 100644 lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp create mode 100644 lib/Target/Mips/MCTargetDesc/MipsABIInfo.h delete mode 100644 lib/Target/Mips/MipsABIInfo.cpp delete mode 100644 lib/Target/Mips/MipsABIInfo.h create mode 100644 lib/Target/NVPTX/NVPTXTargetTransformInfo.h create mode 100644 lib/Target/PowerPC/PPCCallingConv.h create mode 100644 lib/Target/PowerPC/PPCEarlyReturn.cpp create mode 100644 lib/Target/PowerPC/PPCInstrQPX.td create mode 100644 lib/Target/PowerPC/PPCLoopDataPrefetch.cpp create mode 100644 lib/Target/PowerPC/PPCLoopPreIncPrep.cpp create mode 100644 lib/Target/PowerPC/PPCScheduleP8.td create mode 100644 lib/Target/PowerPC/PPCTLSDynamicCall.cpp create mode 100644 lib/Target/PowerPC/PPCTargetTransformInfo.h create mode 100644 lib/Target/PowerPC/PPCVSXCopy.cpp create mode 100644 lib/Target/PowerPC/PPCVSXFMAMutate.cpp create mode 100644 lib/Target/R600/AMDGPUTargetTransformInfo.h create mode 100644 lib/Target/R600/AMDKernelCodeT.h create mode 100644 lib/Target/R600/CIInstructions.td create mode 100644 lib/Target/R600/SIFoldOperands.cpp create mode 100644 lib/Target/R600/SIPrepareScratchRegs.cpp create mode 100644 lib/Target/R600/VIInstrFormats.td create mode 100644 lib/Target/R600/VIInstructions.td create mode 100644 lib/Target/SystemZ/SystemZLDCleanup.cpp delete mode 100644 lib/Target/TargetLibraryInfo.cpp create mode 100644 lib/Target/X86/X86CallFrameOptimization.cpp create mode 100644 lib/Target/X86/X86TargetTransformInfo.h delete mode 100644 lib/Target/XCore/XCoreTargetTransformInfo.cpp create mode 100644 lib/Target/XCore/XCoreTargetTransformInfo.h create mode 100644 lib/Transforms/IPO/LowerBitSets.cpp delete mode 100644 lib/Transforms/InstCombine/InstCombine.h create mode 100644 lib/Transforms/InstCombine/InstCombineInternal.h delete mode 100644 lib/Transforms/InstCombine/InstCombineWorklist.h delete mode 100644 lib/Transforms/Instrumentation/DebugIR.cpp delete mode 100644 lib/Transforms/Instrumentation/DebugIR.h create mode 100644 lib/Transforms/Instrumentation/InstrProfiling.cpp create mode 100644 lib/Transforms/ObjCARC/ARCInstKind.cpp create mode 100644 lib/Transforms/ObjCARC/ARCInstKind.h delete mode 100644 lib/Transforms/ObjCARC/ObjCARCUtil.cpp create mode 100644 lib/Transforms/Scalar/BDCE.cpp create mode 100644 lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp create mode 100644 lib/Transforms/Scalar/LowerExpectIntrinsic.cpp create mode 100644 lib/Transforms/Scalar/PlaceSafepoints.cpp create mode 100644 lib/Transforms/Scalar/RewriteStatepointsForGC.cpp create mode 100644 lib/Transforms/Scalar/StraightLineStrengthReduce.cpp delete mode 100644 lib/Transforms/Utils/LowerExpectIntrinsic.cpp create mode 100644 test/Analysis/AssumptionCache/basic.ll create mode 100644 test/Analysis/BasicAA/struct-geps.ll create mode 100644 test/Analysis/BlockFrequencyInfo/extremely-likely-loop-successor.ll create mode 100644 test/Analysis/CFLAliasAnalysis/asm-global-bugfix.ll create mode 100644 test/Analysis/CFLAliasAnalysis/stratified-attrs-indexing.ll create mode 100644 test/Analysis/CostModel/X86/masked-intrinsic-cost.ll create mode 100644 test/Analysis/Dominators/basic.ll create mode 100644 test/Analysis/Lint/cppeh-catch-intrinsics-clean.ll create mode 100644 test/Analysis/Lint/cppeh-catch-intrinsics.ll create mode 100644 test/Analysis/LoopAccessAnalysis/backward-dep-different-types.ll create mode 100644 test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll create mode 100644 test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll create mode 100644 test/Analysis/ScalarEvolution/incorrect-nsw.ll create mode 100644 test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll create mode 100644 test/Analysis/ScalarEvolution/min-max-exprs.ll create mode 100644 test/Analysis/ScalarEvolution/nw-sub-is-not-nw-add.ll create mode 100644 test/Analysis/ScalarEvolution/pr22179.ll create mode 100644 test/Analysis/ScalarEvolution/pr22641.ll create mode 100644 test/Analysis/ScalarEvolution/pr22674.ll create mode 100644 test/Analysis/ScalarEvolution/scev-expander-incorrect-nowrap.ll create mode 100644 test/Analysis/ScalarEvolution/scev-prestart-nowrap.ll create mode 100644 test/Analysis/ValueTracking/memory-dereferenceable.ll create mode 100644 test/Assembler/alloca-invalid-type-2.ll create mode 100644 test/Assembler/alloca-invalid-type.ll create mode 100644 test/Assembler/call-invalid-1.ll create mode 100644 test/Assembler/debug-info.ll create mode 100644 test/Assembler/distinct-mdnode.ll create mode 100644 test/Assembler/drop-debug-info.ll create mode 100644 test/Assembler/extractvalue-no-idx.ll create mode 100644 test/Assembler/generic-debug-node.ll create mode 100644 test/Assembler/getelementptr_vec_idx4.ll create mode 100644 test/Assembler/gv-invalid-type.ll create mode 100644 test/Assembler/insertvalue-invalid-type-1.ll create mode 100644 test/Assembler/insertvalue-invalid-type.ll create mode 100644 test/Assembler/invalid-attrgrp.ll create mode 100644 test/Assembler/invalid-datalayout1.ll create mode 100644 test/Assembler/invalid-datalayout10.ll create mode 100644 test/Assembler/invalid-datalayout11.ll create mode 100644 test/Assembler/invalid-datalayout12.ll create mode 100644 test/Assembler/invalid-datalayout13.ll create mode 100644 test/Assembler/invalid-datalayout14.ll create mode 100644 test/Assembler/invalid-datalayout15.ll create mode 100644 test/Assembler/invalid-datalayout16.ll create mode 100644 test/Assembler/invalid-datalayout17.ll create mode 100644 test/Assembler/invalid-datalayout18.ll create mode 100644 test/Assembler/invalid-datalayout2.ll create mode 100644 test/Assembler/invalid-datalayout3.ll create mode 100644 test/Assembler/invalid-datalayout4.ll create mode 100644 test/Assembler/invalid-datalayout5.ll create mode 100644 test/Assembler/invalid-datalayout6.ll create mode 100644 test/Assembler/invalid-datalayout7.ll create mode 100644 test/Assembler/invalid-datalayout8.ll create mode 100644 test/Assembler/invalid-datalayout9.ll create mode 100644 test/Assembler/invalid-debug-info-version.ll create mode 100644 test/Assembler/invalid-fwdref2.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-bad.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-missing.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-overflow.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-wrong-type.ll create mode 100644 test/Assembler/invalid-hexint.ll create mode 100644 test/Assembler/invalid-mdbasictype-missing-tag.ll create mode 100644 test/Assembler/invalid-mdcompileunit-language-bad.ll create mode 100644 test/Assembler/invalid-mdcompileunit-language-overflow.ll create mode 100644 test/Assembler/invalid-mdcompileunit-missing-language.ll create mode 100644 test/Assembler/invalid-mdcompositetype-missing-tag.ll create mode 100644 test/Assembler/invalid-mdderivedtype-missing-basetype.ll create mode 100644 test/Assembler/invalid-mdderivedtype-missing-tag.ll create mode 100644 test/Assembler/invalid-mdenumerator-missing-name.ll create mode 100644 test/Assembler/invalid-mdenumerator-missing-value.ll create mode 100644 test/Assembler/invalid-mdexpression-large.ll create mode 100644 test/Assembler/invalid-mdexpression-verify.ll create mode 100644 test/Assembler/invalid-mdfile-missing-directory.ll create mode 100644 test/Assembler/invalid-mdfile-missing-filename.ll create mode 100644 test/Assembler/invalid-mdglobalvariable-missing-name.ll create mode 100644 test/Assembler/invalid-mdimportedentity-missing-parent.ll create mode 100644 test/Assembler/invalid-mdimportedentity-missing-tag.ll create mode 100644 test/Assembler/invalid-mdlexicalblock-missing-parent.ll create mode 100644 test/Assembler/invalid-mdlexicalblockfile-missing-discriminator.ll create mode 100644 test/Assembler/invalid-mdlexicalblockfile-missing-parent.ll create mode 100644 test/Assembler/invalid-mdlocalvariable-missing-name.ll create mode 100644 test/Assembler/invalid-mdlocation-field-bad.ll create mode 100644 test/Assembler/invalid-mdlocation-field-twice.ll create mode 100644 test/Assembler/invalid-mdlocation-missing-scope-2.ll create mode 100644 test/Assembler/invalid-mdlocation-missing-scope.ll create mode 100644 test/Assembler/invalid-mdlocation-overflow-column.ll create mode 100644 test/Assembler/invalid-mdlocation-overflow-line.ll create mode 100644 test/Assembler/invalid-mdnamespace-missing-namespace.ll create mode 100644 test/Assembler/invalid-mdnode-badref.ll create mode 100644 test/Assembler/invalid-mdnode-vector.ll create mode 100644 test/Assembler/invalid-mdnode-vector2.ll create mode 100644 test/Assembler/invalid-mdobjcproperty-missing-name.ll create mode 100644 test/Assembler/invalid-mdsubprogram-missing-name.ll create mode 100644 test/Assembler/invalid-mdsubrange-count-large.ll create mode 100644 test/Assembler/invalid-mdsubrange-count-missing.ll create mode 100644 test/Assembler/invalid-mdsubrange-count-negative.ll create mode 100644 test/Assembler/invalid-mdsubrange-lowerBound-max.ll create mode 100644 test/Assembler/invalid-mdsubrange-lowerBound-min.ll create mode 100644 test/Assembler/invalid-mdsubroutinetype-missing-types.ll create mode 100644 test/Assembler/invalid-mdtemplatetypeparameter-missing-type.ll create mode 100644 test/Assembler/invalid-mdtemplatevalueparameter-missing-tag.ll create mode 100644 test/Assembler/invalid-mdtemplatevalueparameter-missing-type.ll create mode 100644 test/Assembler/invalid-mdtemplatevalueparameter-missing-value.ll create mode 100644 test/Assembler/invalid-metadata-attachment-has-type.ll create mode 100644 test/Assembler/invalid-metadata-function-local-attachments.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-1.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-2.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-3.ll create mode 100644 test/Assembler/invalid-metadata-has-type.ll create mode 100644 test/Assembler/invalid-name2.ll create mode 100644 test/Assembler/invalid-specialized-mdnode.ll create mode 100644 test/Assembler/invalid_cast4.ll create mode 100644 test/Assembler/large-comdat.ll create mode 100644 test/Assembler/mdcompileunit.ll create mode 100644 test/Assembler/mdexpression.ll create mode 100644 test/Assembler/mdglobalvariable.ll create mode 100644 test/Assembler/mdimportedentity.ll create mode 100644 test/Assembler/mdlexicalblock.ll create mode 100644 test/Assembler/mdlocalvariable.ll create mode 100644 test/Assembler/mdlocation.ll create mode 100644 test/Assembler/mdnamespace.ll create mode 100644 test/Assembler/mdobjcproperty.ll create mode 100644 test/Assembler/mdsubprogram.ll create mode 100644 test/Assembler/mdsubrange-empty-array.ll create mode 100644 test/Assembler/mdtemplateparameter.ll create mode 100644 test/Assembler/mdtype-large-values.ll create mode 100644 test/Assembler/metadata-null-operands.ll create mode 100644 test/Assembler/short-hexpair.ll create mode 100644 test/Assembler/unnamed-comdat.ll create mode 100644 test/Bindings/OCaml/transform_utils.ml create mode 100644 test/Bindings/llvm-c/Inputs/invalid.ll.bc create mode 100644 test/Bindings/llvm-c/add_named_metadata_operand.ll create mode 100644 test/Bindings/llvm-c/invalid-bitcode.test create mode 100644 test/Bindings/llvm-c/set_metadata.ll create mode 100644 test/Bitcode/Inputs/invalid-abbrev.bc create mode 100644 test/Bitcode/Inputs/invalid-align.bc create mode 100644 test/Bitcode/Inputs/invalid-bad-abbrev-number.bc create mode 100644 test/Bitcode/Inputs/invalid-bitwidth.bc create mode 100644 test/Bitcode/Inputs/invalid-extractval-array-idx.bc create mode 100644 test/Bitcode/Inputs/invalid-extractval-struct-idx.bc create mode 100644 test/Bitcode/Inputs/invalid-extractval-too-many-idxs.bc create mode 100644 test/Bitcode/Inputs/invalid-insertval-array-idx.bc create mode 100644 test/Bitcode/Inputs/invalid-insertval-struct-idx.bc create mode 100644 test/Bitcode/Inputs/invalid-insertval-too-many-idxs.bc create mode 100644 test/Bitcode/Inputs/invalid-pr20485.bc create mode 100644 test/Bitcode/Inputs/invalid-type-table-forward-ref.bc create mode 100644 test/Bitcode/Inputs/invalid-unexpected-eof.bc create mode 100644 test/Bitcode/drop-debug-info.3.5.ll create mode 100644 test/Bitcode/drop-debug-info.3.5.ll.bc delete mode 100644 test/Bitcode/drop-debug-info.ll create mode 100644 test/Bitcode/function-local-metadata.3.5.ll create mode 100644 test/Bitcode/function-local-metadata.3.5.ll.bc create mode 100644 test/Bitcode/invalid.test create mode 100644 test/Bitcode/mdstring-high-bits.ll create mode 100644 test/Bitcode/metadata.3.5.ll create mode 100644 test/Bitcode/metadata.3.5.ll.bc create mode 100644 test/Bitcode/weak-macho-3.5.ll create mode 100644 test/Bitcode/weak-macho-3.5.ll.bc create mode 100644 test/CodeGen/AArch64/aarch64-2014-12-02-combine-soften.ll create mode 100644 test/CodeGen/AArch64/argument-blocks.ll create mode 100644 test/CodeGen/AArch64/arm64-stackmap-nops.ll create mode 100644 test/CodeGen/AArch64/bitcast-v2i8.ll create mode 100644 test/CodeGen/AArch64/br-to-eh-lpad.ll create mode 100644 test/CodeGen/AArch64/fast-isel-branch-cond-split.ll create mode 100644 test/CodeGen/AArch64/fast-isel-memcpy.ll create mode 100644 test/CodeGen/AArch64/fdiv-combine.ll create mode 100644 test/CodeGen/AArch64/ghc-cc.ll create mode 100644 test/CodeGen/AArch64/implicit-sret.ll create mode 100644 test/CodeGen/AArch64/large_shift.ll create mode 100644 test/CodeGen/AArch64/machine_cse_impdef_killflags.ll create mode 100644 test/CodeGen/AArch64/or-combine.ll create mode 100644 test/CodeGen/AArch64/setcc-type-mismatch.ll create mode 100644 test/CodeGen/ARM/2015-01-21-thumbv4t-ldstr-opt.ll create mode 100644 test/CodeGen/ARM/Windows/stack-probe-non-default.ll create mode 100644 test/CodeGen/ARM/aggregate-padding.ll create mode 100644 test/CodeGen/ARM/crc32.ll create mode 100644 test/CodeGen/ARM/ghc-tcreturn-lowered.ll create mode 100644 test/CodeGen/ARM/isel-v8i32-crash.ll create mode 100644 test/CodeGen/ARM/krait-cpu-div-attribute.ll delete mode 100644 test/CodeGen/ARM/odr_comdat.ll create mode 100644 test/CodeGen/ARM/setcc-type-mismatch.ll create mode 100644 test/CodeGen/ARM/stack-alignment.ll create mode 100644 test/CodeGen/ARM/tail-call-weak.ll create mode 100644 test/CodeGen/ARM/thumb_indirect_calls.ll create mode 100644 test/CodeGen/ARM/vector-load.ll create mode 100644 test/CodeGen/ARM/vector-store.ll create mode 100644 test/CodeGen/BPF/alu8.ll create mode 100644 test/CodeGen/BPF/atomics.ll create mode 100644 test/CodeGen/BPF/basictest.ll create mode 100644 test/CodeGen/BPF/byval.ll create mode 100644 test/CodeGen/BPF/cc_args.ll create mode 100644 test/CodeGen/BPF/cc_ret.ll create mode 100644 test/CodeGen/BPF/cmp.ll create mode 100644 test/CodeGen/BPF/ex1.ll create mode 100644 test/CodeGen/BPF/intrinsics.ll create mode 100644 test/CodeGen/BPF/lit.local.cfg create mode 100644 test/CodeGen/BPF/load.ll create mode 100644 test/CodeGen/BPF/loops.ll create mode 100644 test/CodeGen/BPF/many_args1.ll create mode 100644 test/CodeGen/BPF/many_args2.ll create mode 100644 test/CodeGen/BPF/sanity.ll create mode 100644 test/CodeGen/BPF/setcc.ll create mode 100644 test/CodeGen/BPF/shifts.ll create mode 100644 test/CodeGen/BPF/sockex2.ll create mode 100644 test/CodeGen/BPF/struct_ret1.ll create mode 100644 test/CodeGen/BPF/struct_ret2.ll create mode 100644 test/CodeGen/BPF/vararg1.ll create mode 100644 test/CodeGen/Generic/empty-phi.ll create mode 100644 test/CodeGen/Generic/overloaded-intrinsic-name.ll delete mode 100644 test/CodeGen/Hexagon/cmp-not.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/alu32_alu.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/alu32_perm.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/cr.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_alu.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_bit.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_complex.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_fp.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_mpy.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_perm.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_pred.ll create mode 100644 test/CodeGen/Hexagon/intrinsics/xtype_shift.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/overflt.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/retabi.ll create mode 100644 test/CodeGen/Mips/cconv/arguments-struct.ll create mode 100644 test/CodeGen/Mips/cconv/arguments-varargs-small-structs-byte.ll create mode 100644 test/CodeGen/Mips/cconv/arguments-varargs-small-structs-combinations.ll create mode 100644 test/CodeGen/Mips/cconv/arguments-varargs-small-structs-multiple-args.ll delete mode 100644 test/CodeGen/Mips/fptr2.ll create mode 100644 test/CodeGen/Mips/inlineasm-assembler-directives.ll create mode 100644 test/CodeGen/Mips/llvm-ir/add.ll create mode 100644 test/CodeGen/Mips/llvm-ir/and.ll create mode 100644 test/CodeGen/Mips/llvm-ir/ashr.ll create mode 100644 test/CodeGen/Mips/llvm-ir/lshr.ll create mode 100644 test/CodeGen/Mips/llvm-ir/or.ll create mode 100644 test/CodeGen/Mips/llvm-ir/sdiv.ll create mode 100644 test/CodeGen/Mips/llvm-ir/select.ll create mode 100644 test/CodeGen/Mips/llvm-ir/shl.ll create mode 100644 test/CodeGen/Mips/llvm-ir/srem.ll create mode 100644 test/CodeGen/Mips/llvm-ir/sub.ll create mode 100644 test/CodeGen/Mips/llvm-ir/udiv.ll create mode 100644 test/CodeGen/Mips/llvm-ir/urem.ll create mode 100644 test/CodeGen/Mips/llvm-ir/xor.ll create mode 100644 test/CodeGen/Mips/micromips-and16.ll create mode 100644 test/CodeGen/Mips/micromips-atomic1.ll create mode 100644 test/CodeGen/Mips/micromips-compact-branches.ll create mode 100644 test/CodeGen/Mips/micromips-compact-jump.ll create mode 100644 test/CodeGen/Mips/micromips-delay-slot-jr.ll create mode 100644 test/CodeGen/Mips/micromips-li.ll create mode 100644 test/CodeGen/Mips/micromips-or16.ll create mode 100644 test/CodeGen/Mips/micromips-sw-lw-16.ll create mode 100644 test/CodeGen/Mips/micromips-xor16.ll create mode 100644 test/CodeGen/Mips/mips64sinttofpsf.ll create mode 100644 test/CodeGen/Mips/named-register-n32.ll create mode 100644 test/CodeGen/Mips/named-register-n64.ll create mode 100644 test/CodeGen/Mips/named-register-o32.ll create mode 100644 test/CodeGen/Mips/no-odd-spreg-msa.ll create mode 100644 test/CodeGen/NVPTX/bug22246.ll create mode 100644 test/CodeGen/NVPTX/bug22322.ll create mode 100644 test/CodeGen/NVPTX/fma-assoc.ll create mode 100644 test/CodeGen/NVPTX/nounroll.ll create mode 100644 test/CodeGen/NVPTX/nvcl-param-align.ll create mode 100644 test/CodeGen/NVPTX/vector-global.ll create mode 100644 test/CodeGen/PowerPC/add-fi.ll create mode 100644 test/CodeGen/PowerPC/addi-licm.ll create mode 100644 test/CodeGen/PowerPC/arr-fp-arg-no-copy.ll create mode 100644 test/CodeGen/PowerPC/bperm.ll create mode 100644 test/CodeGen/PowerPC/cmpb-ppc32.ll create mode 100644 test/CodeGen/PowerPC/cmpb.ll create mode 100644 test/CodeGen/PowerPC/code-align.ll create mode 100644 test/CodeGen/PowerPC/constants-i64.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-const.ll create mode 100644 test/CodeGen/PowerPC/fdiv-combine.ll create mode 100644 test/CodeGen/PowerPC/flt-preinc.ll create mode 100644 test/CodeGen/PowerPC/fma-assoc.ll create mode 100644 test/CodeGen/PowerPC/fma-ext.ll create mode 100644 test/CodeGen/PowerPC/fp-to-int-ext.ll create mode 100644 test/CodeGen/PowerPC/fp-to-int-to-fp.ll create mode 100644 test/CodeGen/PowerPC/i1-ext-fold.ll create mode 100644 test/CodeGen/PowerPC/ia-mem-r0.ll create mode 100644 test/CodeGen/PowerPC/ia-neg-const.ll create mode 100644 test/CodeGen/PowerPC/lbz-from-ld-shift.ll create mode 100644 test/CodeGen/PowerPC/ld-st-upd.ll create mode 100644 test/CodeGen/PowerPC/ldtoc-inv.ll create mode 100644 test/CodeGen/PowerPC/loop-data-prefetch.ll create mode 100644 test/CodeGen/PowerPC/no-extra-fp-conv-ldst.ll create mode 100644 test/CodeGen/PowerPC/no-pref-jumps.ll create mode 100644 test/CodeGen/PowerPC/p8-isel-sched.ll create mode 100644 test/CodeGen/PowerPC/post-ra-ec.ll create mode 100644 test/CodeGen/PowerPC/ppc32-cyclecounter.ll create mode 100644 test/CodeGen/PowerPC/ppc64-anyregcc-crash.ll create mode 100644 test/CodeGen/PowerPC/ppc64-anyregcc.ll create mode 100644 test/CodeGen/PowerPC/ppc64-fastcc-fast-isel.ll create mode 100644 test/CodeGen/PowerPC/ppc64-fastcc.ll create mode 100644 test/CodeGen/PowerPC/ppc64-func-desc-hoist.ll create mode 100644 test/CodeGen/PowerPC/ppc64-gep-opt.ll create mode 100644 test/CodeGen/PowerPC/ppc64-icbt-pwr7.ll create mode 100644 test/CodeGen/PowerPC/ppc64-icbt-pwr8.ll create mode 100644 test/CodeGen/PowerPC/ppc64-nonfunc-calls.ll create mode 100644 test/CodeGen/PowerPC/ppc64-patchpoint.ll create mode 100644 test/CodeGen/PowerPC/ppc64-r2-alloc.ll create mode 100644 test/CodeGen/PowerPC/ppc64-stackmap-nops.ll create mode 100644 test/CodeGen/PowerPC/ppc64-stackmap.ll create mode 100644 test/CodeGen/PowerPC/preincprep-invoke.ll create mode 100644 test/CodeGen/PowerPC/qpx-bv-sint.ll create mode 100644 test/CodeGen/PowerPC/qpx-bv.ll create mode 100644 test/CodeGen/PowerPC/qpx-func-clobber.ll create mode 100644 test/CodeGen/PowerPC/qpx-load.ll create mode 100644 test/CodeGen/PowerPC/qpx-recipest.ll create mode 100644 test/CodeGen/PowerPC/qpx-rounding-ops.ll create mode 100644 test/CodeGen/PowerPC/qpx-s-load.ll create mode 100644 test/CodeGen/PowerPC/qpx-s-sel.ll create mode 100644 test/CodeGen/PowerPC/qpx-s-store.ll create mode 100644 test/CodeGen/PowerPC/qpx-sel.ll create mode 100644 test/CodeGen/PowerPC/qpx-store.ll create mode 100644 test/CodeGen/PowerPC/qpx-unalperm.ll create mode 100644 test/CodeGen/PowerPC/retaddr2.ll create mode 100644 test/CodeGen/PowerPC/rm-zext.ll create mode 100644 test/CodeGen/PowerPC/sdiv-pow2.ll create mode 100644 test/CodeGen/PowerPC/subreg-postra-2.ll create mode 100644 test/CodeGen/PowerPC/subreg-postra.ll create mode 100644 test/CodeGen/PowerPC/tls-cse.ll create mode 100644 test/CodeGen/PowerPC/vec_clz.ll create mode 100644 test/CodeGen/PowerPC/vec_popcnt.ll create mode 100644 test/CodeGen/PowerPC/vec_veqv_vnand_vorc.ll create mode 100644 test/CodeGen/PowerPC/vsel-prom.ll create mode 100644 test/CodeGen/PowerPC/vsx-infl-copy1.ll create mode 100644 test/CodeGen/PowerPC/vsx-infl-copy2.ll create mode 100644 test/CodeGen/PowerPC/vsx-ldst-builtin-le.ll create mode 100644 test/CodeGen/PowerPC/vsx-spill-norwstore.ll create mode 100644 test/CodeGen/PowerPC/vsx_insert_extract_le.ll create mode 100644 test/CodeGen/PowerPC/vsx_shuffle_le.ll create mode 100644 test/CodeGen/PowerPC/xxleqv_xxlnand_xxlorc.ll create mode 100644 test/CodeGen/PowerPC/zext-free.ll create mode 100644 test/CodeGen/R600/cvt_flr_i32_f32.ll create mode 100644 test/CodeGen/R600/cvt_rpi_i32_f32.ll create mode 100644 test/CodeGen/R600/ds_read2_offset_order.ll create mode 100644 test/CodeGen/R600/endcf-loop-header.ll create mode 100644 test/CodeGen/R600/extload-private.ll create mode 100644 test/CodeGen/R600/fdiv.f64.ll delete mode 100644 test/CodeGen/R600/fdiv64.ll create mode 100644 test/CodeGen/R600/ffloor.f64.ll create mode 100644 test/CodeGen/R600/fma-combine.ll create mode 100644 test/CodeGen/R600/fmax_legacy.f64.ll create mode 100644 test/CodeGen/R600/fmin_legacy.f64.ll create mode 100644 test/CodeGen/R600/fp-classify.ll create mode 100644 test/CodeGen/R600/global-extload-i1.ll create mode 100644 test/CodeGen/R600/global-extload-i16.ll create mode 100644 test/CodeGen/R600/global-extload-i32.ll create mode 100644 test/CodeGen/R600/global-extload-i8.ll create mode 100644 test/CodeGen/R600/hsa.ll create mode 100644 test/CodeGen/R600/inline-asm.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.class.ll delete mode 100644 test/CodeGen/R600/llvm.SI.fs.interp.constant.ll create mode 100644 test/CodeGen/R600/llvm.SI.fs.interp.ll create mode 100644 test/CodeGen/R600/llvm.SI.sendmsg-m0.ll delete mode 100644 test/CodeGen/R600/llvm.floor.ll create mode 100644 test/CodeGen/R600/llvm.round.f64.ll delete mode 100644 test/CodeGen/R600/llvm.trunc.ll create mode 100644 test/CodeGen/R600/mad-combine.ll create mode 100644 test/CodeGen/R600/madak.ll create mode 100644 test/CodeGen/R600/madmk.ll create mode 100644 test/CodeGen/R600/no-shrink-extloads.ll create mode 100644 test/CodeGen/R600/operand-folding.ll create mode 100644 test/CodeGen/R600/scratch-buffer.ll create mode 100644 test/CodeGen/R600/sdivrem64.ll create mode 100644 test/CodeGen/R600/subreg-coalescer-crash.ll create mode 100644 test/CodeGen/R600/trunc-cmp-constant.ll create mode 100644 test/CodeGen/R600/tti-unroll-prefs.ll create mode 100644 test/CodeGen/SystemZ/tls-02.ll create mode 100644 test/CodeGen/SystemZ/tls-03.ll create mode 100644 test/CodeGen/SystemZ/tls-04.ll create mode 100644 test/CodeGen/SystemZ/tls-05.ll create mode 100644 test/CodeGen/SystemZ/tls-06.ll create mode 100644 test/CodeGen/SystemZ/tls-07.ll create mode 100644 test/CodeGen/Thumb/stack-access.ll create mode 100644 test/CodeGen/Thumb2/constant-islands-jump-table.ll create mode 100644 test/CodeGen/Thumb2/constant-islands-new-island-padding.ll delete mode 100644 test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll delete mode 100644 test/CodeGen/X86/2007-04-25-MMX-PADDQ.ll delete mode 100644 test/CodeGen/X86/2007-06-15-IntToMMX.ll delete mode 100644 test/CodeGen/X86/2008-10-06-MMXISelBug.ll delete mode 100644 test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll delete mode 100644 test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll delete mode 100644 test/CodeGen/X86/2009-08-02-mmx-scalar-to-vector.ll delete mode 100644 test/CodeGen/X86/2010-01-07-UAMemFeature.ll delete mode 100644 test/CodeGen/X86/2010-04-23-mmx-movdq2q.ll delete mode 100644 test/CodeGen/X86/2012-05-19-avx2-store.ll delete mode 100644 test/CodeGen/X86/avx1-stack-reload-folding.ll create mode 100644 test/CodeGen/X86/avx2-pmovxrm-intrinsics.ll create mode 100755 test/CodeGen/X86/avx512-i1test.ll create mode 100644 test/CodeGen/X86/avx512-intel-ocl.ll create mode 100644 test/CodeGen/X86/avx512-logic.ll create mode 100644 test/CodeGen/X86/avx512-round.ll create mode 100644 test/CodeGen/X86/avx512bw-arith.ll create mode 100644 test/CodeGen/X86/avx512bwvl-arith.ll create mode 100644 test/CodeGen/X86/avx512vl-arith.ll create mode 100644 test/CodeGen/X86/avx512vl-logic.ll create mode 100644 test/CodeGen/X86/bitcast-mmx.ll delete mode 100644 test/CodeGen/X86/break-avx-dep.ll create mode 100644 test/CodeGen/X86/break-false-dep.ll delete mode 100644 test/CodeGen/X86/break-sse-dep.ll create mode 100644 test/CodeGen/X86/coalesce_commute_subreg.ll create mode 100644 test/CodeGen/X86/commute-clmul.ll create mode 100644 test/CodeGen/X86/commute-fcmp.ll create mode 100644 test/CodeGen/X86/commute-xop.ll create mode 100644 test/CodeGen/X86/constant-combines.ll create mode 100644 test/CodeGen/X86/constant-hoisting-optnone.ll create mode 100644 test/CodeGen/X86/copysign-constant-magnitude.ll delete mode 100644 test/CodeGen/X86/copysign-zero.ll create mode 100644 test/CodeGen/X86/cppeh-catch-all.ll create mode 100644 test/CodeGen/X86/cppeh-catch-scalar.ll create mode 100644 test/CodeGen/X86/cppeh-frame-vars.ll create mode 100644 test/CodeGen/X86/cpus.ll create mode 100644 test/CodeGen/X86/dbg-combine.ll create mode 100644 test/CodeGen/X86/dwarf-eh-prepare.ll create mode 100644 test/CodeGen/X86/equiv_with_fndef.ll create mode 100644 test/CodeGen/X86/equiv_with_vardef.ll create mode 100644 test/CodeGen/X86/fast-isel-call-bool.ll create mode 100644 test/CodeGen/X86/fast-isel-double-half-convertion.ll create mode 100644 test/CodeGen/X86/fast-isel-float-half-convertion.ll create mode 100644 test/CodeGen/X86/fast-isel-fptrunc-fpext.ll create mode 100644 test/CodeGen/X86/fast-isel-int-float-conversion.ll create mode 100644 test/CodeGen/X86/fastmath-float-half-conversion.ll create mode 100644 test/CodeGen/X86/float-conv-elim.ll create mode 100644 test/CodeGen/X86/fold-load-unops.ll create mode 100644 test/CodeGen/X86/fp-double-rounding.ll create mode 100644 test/CodeGen/X86/frameallocate.ll create mode 100644 test/CodeGen/X86/global-sections-comdat.ll create mode 100644 test/CodeGen/X86/huge-stack-offset.ll create mode 100644 test/CodeGen/X86/i1narrowfail.ll create mode 100644 test/CodeGen/X86/imul.ll delete mode 100644 test/CodeGen/X86/imul64-lea.ll create mode 100644 test/CodeGen/X86/init-priority.ll create mode 100644 test/CodeGen/X86/insertps-O0-bug.ll create mode 100644 test/CodeGen/X86/large-code-model-isel.ll create mode 100644 test/CodeGen/X86/logical-load-fold.ll create mode 100644 test/CodeGen/X86/lower-vec-shift-2.ll create mode 100644 test/CodeGen/X86/masked_memop.ll create mode 100644 test/CodeGen/X86/misched-code-difference-with-debug.ll create mode 100644 test/CodeGen/X86/mmx-arg-passing-x86-64.ll delete mode 100644 test/CodeGen/X86/mmx-arg-passing2.ll delete mode 100644 test/CodeGen/X86/mmx-bitcast-to-i64.ll create mode 100644 test/CodeGen/X86/mmx-bitcast.ll delete mode 100644 test/CodeGen/X86/mmx-builtins.ll delete mode 100644 test/CodeGen/X86/mmx-emms.ll create mode 100644 test/CodeGen/X86/mmx-fold-load.ll delete mode 100644 test/CodeGen/X86/mmx-insert-element.ll create mode 100644 test/CodeGen/X86/mmx-intrinsics.ll delete mode 100644 test/CodeGen/X86/mmx-pinsrw.ll delete mode 100644 test/CodeGen/X86/mmx-punpckhdq.ll delete mode 100644 test/CodeGen/X86/mmx-s2v.ll delete mode 100644 test/CodeGen/X86/mmx-shift.ll delete mode 100644 test/CodeGen/X86/mmx-shuffle.ll create mode 100644 test/CodeGen/X86/movtopush.ll create mode 100644 test/CodeGen/X86/musttail-fastcall.ll delete mode 100644 test/CodeGen/X86/no-compact-unwind.ll create mode 100644 test/CodeGen/X86/non-unique-sections.ll delete mode 100644 test/CodeGen/X86/odr_comdat.ll create mode 100644 test/CodeGen/X86/pr21792.ll create mode 100644 test/CodeGen/X86/pr22019.ll create mode 100644 test/CodeGen/X86/pr22103.ll create mode 100644 test/CodeGen/X86/prologuedata.ll create mode 100644 test/CodeGen/X86/regalloc-reconcile-broken-hints.ll create mode 100644 test/CodeGen/X86/seh-basic.ll create mode 100644 test/CodeGen/X86/seh-catch-all.ll create mode 100644 test/CodeGen/X86/seh-filter.ll create mode 100755 test/CodeGen/X86/seh-finally.ll create mode 100644 test/CodeGen/X86/seh-safe-div.ll create mode 100644 test/CodeGen/X86/selectiondag-crash.ll create mode 100644 test/CodeGen/X86/sibcall-win64.ll create mode 100644 test/CodeGen/X86/sjlj-baseptr.ll create mode 100644 test/CodeGen/X86/slow-div.ll create mode 100644 test/CodeGen/X86/splat-const.ll create mode 100644 test/CodeGen/X86/sret-implicit.ll create mode 100644 test/CodeGen/X86/sse-unaligned-mem-feature.ll create mode 100644 test/CodeGen/X86/sse2-intrinsics-x86-upgrade.ll create mode 100644 test/CodeGen/X86/sse41-pmovxrm-intrinsics.ll create mode 100644 test/CodeGen/X86/stack-folding-fp-avx1.ll create mode 100644 test/CodeGen/X86/stack-folding-fp-sse42.ll create mode 100644 test/CodeGen/X86/stack-folding-int-avx1.ll create mode 100644 test/CodeGen/X86/stack-folding-int-avx2.ll create mode 100644 test/CodeGen/X86/stack-folding-int-sse42.ll create mode 100644 test/CodeGen/X86/stack-folding-xop.ll create mode 100644 test/CodeGen/X86/stack-probe-size.ll create mode 100644 test/CodeGen/X86/stack-protector-weight.ll create mode 100644 test/CodeGen/X86/statepoint-call-lowering.ll create mode 100644 test/CodeGen/X86/statepoint-forward.ll create mode 100644 test/CodeGen/X86/statepoint-stack-usage.ll create mode 100644 test/CodeGen/X86/statepoint-stackmap-format.ll create mode 100644 test/CodeGen/X86/switch-default-only.ll create mode 100644 test/CodeGen/X86/switch-jump-table.ll create mode 100644 test/CodeGen/X86/tail-call-win64.ll create mode 100644 test/CodeGen/X86/unaligned-32-byte-memops.ll create mode 100644 test/CodeGen/X86/vec-loadsingles-alignment.ll delete mode 100644 test/CodeGen/X86/vec_clear.ll create mode 100644 test/CodeGen/X86/vec_extract-avx.ll create mode 100644 test/CodeGen/X86/vec_extract-mmx.ll create mode 100644 test/CodeGen/X86/vec_insert-mmx.ll create mode 100644 test/CodeGen/X86/vector-ctpop.ll create mode 100644 test/CodeGen/X86/vector-shuffle-512-v16.ll create mode 100644 test/CodeGen/X86/vector-shuffle-mmx.ll create mode 100644 test/CodeGen/X86/vector-trunc.ll create mode 100644 test/CodeGen/X86/vector-zmov.ll create mode 100644 test/CodeGen/X86/win64_frame.ll create mode 100644 test/CodeGen/X86/win_eh_prepare.ll create mode 100644 test/CodeGen/X86/x32-lea-1.ll create mode 100644 test/CodeGen/X86/x86-64-baseptr.ll create mode 100644 test/CodeGen/X86/x86-inline-asm-validation.ll create mode 100644 test/DebugInfo/AArch64/cfi-eof-prologue.ll create mode 100644 test/DebugInfo/AArch64/coalescing.ll create mode 100644 test/DebugInfo/AArch64/frameindices.ll create mode 100644 test/DebugInfo/ARM/cfi-eof-prologue.ll create mode 100644 test/DebugInfo/ARM/line.test create mode 100644 test/DebugInfo/Inputs/line.ll create mode 100644 test/DebugInfo/Mips/fn-call-line.ll create mode 100644 test/DebugInfo/PDB/Inputs/empty.cpp create mode 100644 test/DebugInfo/PDB/Inputs/empty.pdb create mode 100644 test/DebugInfo/PDB/Inputs/symbolformat-fpo.cpp create mode 100644 test/DebugInfo/PDB/Inputs/symbolformat.cpp create mode 100644 test/DebugInfo/PDB/Inputs/symbolformat.pdb create mode 100644 test/DebugInfo/PDB/lit.local.cfg create mode 100644 test/DebugInfo/PDB/pdbdump-flags.test create mode 100644 test/DebugInfo/PDB/pdbdump-symbol-format.test create mode 100644 test/DebugInfo/PowerPC/line.test delete mode 100644 test/DebugInfo/X86/2010-08-10-DbgConstant.ll create mode 100644 test/DebugInfo/X86/asm-macro-line-number.s create mode 100644 test/DebugInfo/X86/constant-aggregate.ll create mode 100644 test/DebugInfo/X86/float_const.ll create mode 100644 test/DebugInfo/X86/line.test create mode 100644 test/DebugInfo/X86/memberfnptr.ll create mode 100644 test/DebugInfo/X86/nophysreg.ll create mode 100644 test/DebugInfo/X86/sroasplit-1.ll create mode 100644 test/DebugInfo/X86/sroasplit-2.ll create mode 100644 test/DebugInfo/X86/sroasplit-3.ll create mode 100644 test/DebugInfo/X86/sroasplit-4.ll create mode 100644 test/DebugInfo/X86/sroasplit-5.ll create mode 100644 test/DebugInfo/X86/union-const.ll create mode 100644 test/DebugInfo/block-asan.ll delete mode 100644 test/DebugInfo/duplicate_inline.ll delete mode 100644 test/DebugInfo/global-with-type-context.ll create mode 100644 test/DebugInfo/incorrect-variable-debugloc1.ll create mode 100644 test/DebugInfo/location-verifier.ll create mode 100644 test/DebugInfo/multiline.ll create mode 100644 test/DebugInfo/piece-verifier.ll delete mode 100644 test/ExecutionEngine/2002-12-16-ArgTest.ll delete mode 100644 test/ExecutionEngine/2003-01-04-ArgumentBug.ll delete mode 100644 test/ExecutionEngine/2003-01-04-LoopTest.ll delete mode 100644 test/ExecutionEngine/2003-01-04-PhiTest.ll delete mode 100644 test/ExecutionEngine/2003-01-09-SARTest.ll delete mode 100644 test/ExecutionEngine/2003-01-10-FUCOM.ll delete mode 100644 test/ExecutionEngine/2003-01-15-AlignmentTest.ll delete mode 100644 test/ExecutionEngine/2003-05-06-LivenessClobber.ll delete mode 100644 test/ExecutionEngine/2003-05-07-ArgumentTest.ll delete mode 100644 test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll delete mode 100644 test/ExecutionEngine/2003-06-04-bzip2-bug.ll delete mode 100644 test/ExecutionEngine/2003-06-05-PHIBug.ll delete mode 100644 test/ExecutionEngine/2003-08-15-AllocaAssertion.ll delete mode 100644 test/ExecutionEngine/2003-08-21-EnvironmentTest.ll delete mode 100644 test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll delete mode 100644 test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll delete mode 100644 test/ExecutionEngine/2005-12-02-TailCallBug.ll delete mode 100644 test/ExecutionEngine/2007-12-10-APIntLoadStore.ll delete mode 100644 test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll delete mode 100644 test/ExecutionEngine/MCJIT/2010-01-15-UndefValue.ll delete mode 100644 test/ExecutionEngine/MCJIT/non-extern-addend-smallcodemodel.ll create mode 100644 test/ExecutionEngine/OrcJIT/2002-12-16-ArgTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-04-ArgumentBug.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-04-LoopTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-04-PhiTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-09-SARTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-10-FUCOM.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-01-15-AlignmentTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-05-06-LivenessClobber.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-05-07-ArgumentTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-05-11-PHIRegAllocBug.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-06-04-bzip2-bug.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-06-05-PHIBug.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-08-15-AllocaAssertion.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-08-21-EnvironmentTest.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-08-23-RegisterAllocatePhysReg.ll create mode 100644 test/ExecutionEngine/OrcJIT/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll create mode 100644 test/ExecutionEngine/OrcJIT/2005-12-02-TailCallBug.ll create mode 100644 test/ExecutionEngine/OrcJIT/2007-12-10-APIntLoadStore.ll create mode 100644 test/ExecutionEngine/OrcJIT/2008-06-05-APInt-OverAShr.ll create mode 100644 test/ExecutionEngine/OrcJIT/2013-04-04-RelocAddend.ll create mode 100644 test/ExecutionEngine/OrcJIT/Inputs/cross-module-b.ll create mode 100644 test/ExecutionEngine/OrcJIT/Inputs/multi-module-b.ll create mode 100644 test/ExecutionEngine/OrcJIT/Inputs/multi-module-c.ll create mode 100644 test/ExecutionEngine/OrcJIT/Inputs/multi-module-eh-b.ll create mode 100644 test/ExecutionEngine/OrcJIT/cross-module-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/cross-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/eh-lg-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/eh-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/eh.ll create mode 100644 test/ExecutionEngine/OrcJIT/fpbitcast.ll create mode 100644 test/ExecutionEngine/OrcJIT/hello-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/hello.ll create mode 100644 test/ExecutionEngine/OrcJIT/hello2.ll create mode 100644 test/ExecutionEngine/OrcJIT/lit.local.cfg create mode 100644 test/ExecutionEngine/OrcJIT/load-object-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/multi-module-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/multi-module-eh-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/multi-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/non-extern-addend.ll create mode 100644 test/ExecutionEngine/OrcJIT/pr13727.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/Inputs/cross-module-b.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/Inputs/multi-module-b.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/Inputs/multi-module-c.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/cross-module-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/cross-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/lit.local.cfg create mode 100644 test/ExecutionEngine/OrcJIT/remote/multi-module-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/multi-module-sm-pic-a.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/simpletest-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/stubs-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/stubs-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-common-symbols-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-data-align-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-fp-no-external-funcs-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-global-init-nonzero-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-global-init-nonzero-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-ptr-reloc-remote.ll create mode 100644 test/ExecutionEngine/OrcJIT/remote/test-ptr-reloc-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/simplesttest.ll create mode 100644 test/ExecutionEngine/OrcJIT/simpletest.ll create mode 100644 test/ExecutionEngine/OrcJIT/stubs-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/stubs.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-arith.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-branch.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-call-no-external-funcs.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-call.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-cast.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-common-symbols-alignment.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-common-symbols.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-constantexpr.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-data-align.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-fp-no-external-funcs.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-fp.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-global-ctors.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-global-init-nonzero-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-global-init-nonzero.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-global.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-loadstore.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-local.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-logical.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-loop.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-phi.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-ptr-reloc-sm-pic.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-ptr-reloc.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-ret.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-return.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-setcond-fp.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-setcond-int.ll create mode 100644 test/ExecutionEngine/OrcJIT/test-shift.ll delete mode 100644 test/ExecutionEngine/fpbitcast.ll delete mode 100644 test/ExecutionEngine/hello.ll delete mode 100644 test/ExecutionEngine/hello2.ll delete mode 100644 test/ExecutionEngine/simplesttest.ll delete mode 100644 test/ExecutionEngine/simpletest.ll delete mode 100644 test/ExecutionEngine/stubs.ll delete mode 100644 test/ExecutionEngine/test-arith.ll delete mode 100644 test/ExecutionEngine/test-branch.ll delete mode 100644 test/ExecutionEngine/test-call-no-external-funcs.ll delete mode 100644 test/ExecutionEngine/test-call.ll delete mode 100644 test/ExecutionEngine/test-cast.ll delete mode 100644 test/ExecutionEngine/test-common-symbols.ll delete mode 100644 test/ExecutionEngine/test-constantexpr.ll delete mode 100644 test/ExecutionEngine/test-fp-no-external-funcs.ll delete mode 100644 test/ExecutionEngine/test-fp.ll delete mode 100644 test/ExecutionEngine/test-global-init-nonzero.ll delete mode 100644 test/ExecutionEngine/test-global.ll delete mode 100644 test/ExecutionEngine/test-loadstore.ll delete mode 100644 test/ExecutionEngine/test-local.ll delete mode 100644 test/ExecutionEngine/test-logical.ll delete mode 100644 test/ExecutionEngine/test-loop.ll delete mode 100644 test/ExecutionEngine/test-phi.ll delete mode 100644 test/ExecutionEngine/test-ret.ll delete mode 100644 test/ExecutionEngine/test-return.ll delete mode 100644 test/ExecutionEngine/test-setcond-fp.ll delete mode 100644 test/ExecutionEngine/test-setcond-int.ll delete mode 100644 test/ExecutionEngine/test-shift.ll create mode 100644 test/Feature/prologuedata.ll create mode 100644 test/Feature/seh-nounwind.ll create mode 100644 test/FileCheck/same.txt create mode 100644 test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll delete mode 100644 test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll create mode 100644 test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll create mode 100644 test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll create mode 100644 test/Instrumentation/InstrProfiling/linkage.ll create mode 100644 test/Instrumentation/InstrProfiling/no-counters.ll create mode 100644 test/Instrumentation/InstrProfiling/noruntime.ll create mode 100644 test/Instrumentation/InstrProfiling/platform.ll create mode 100644 test/Instrumentation/InstrProfiling/profiling.ll delete mode 100644 test/Instrumentation/MemorySanitizer/do-not-emit-module-limits.ll create mode 100644 test/Instrumentation/MemorySanitizer/origin-alignment.ll create mode 100644 test/Instrumentation/MemorySanitizer/store-long-origin.ll delete mode 100644 test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll create mode 100644 test/Instrumentation/ThreadSanitizer/capture.ll create mode 100644 test/Instrumentation/ThreadSanitizer/unaligned.ll create mode 100644 test/JitListener/multiple.ll create mode 100644 test/JitListener/simple.ll delete mode 100644 test/JitListener/test-common-symbols.ll delete mode 100644 test/JitListener/test-inline.ll delete mode 100644 test/JitListener/test-parameters.ll create mode 100644 test/LTO/ARM/inline-asm.ll create mode 100644 test/LTO/ARM/lit.local.cfg create mode 100644 test/LTO/ARM/runtime-library-subtarget.ll delete mode 100644 test/LTO/Inputs/bcsection.macho.s delete mode 100644 test/LTO/Inputs/bcsection.s create mode 100644 test/LTO/X86/Inputs/bcsection.macho.s create mode 100644 test/LTO/X86/Inputs/bcsection.s create mode 100644 test/LTO/X86/Inputs/invalid.ll.bc create mode 100644 test/LTO/X86/Inputs/list-symbols.ll create mode 100644 test/LTO/X86/attrs.ll create mode 100644 test/LTO/X86/bcsection.ll create mode 100644 test/LTO/X86/cfi_endproc.ll create mode 100644 test/LTO/X86/current-section.ll create mode 100644 test/LTO/X86/diagnostic-handler-remarks.ll create mode 100644 test/LTO/X86/invalid.ll create mode 100644 test/LTO/X86/jump-table-type.ll create mode 100644 test/LTO/X86/keep-used-puts-during-instcombine.ll create mode 100644 test/LTO/X86/linkonce_odr_func.ll create mode 100644 test/LTO/X86/list-symbols.ll create mode 100644 test/LTO/X86/lit.local.cfg create mode 100644 test/LTO/X86/no-undefined-puts-when-implemented.ll create mode 100644 test/LTO/X86/private-symbol.ll create mode 100644 test/LTO/X86/runtime-library.ll create mode 100644 test/LTO/X86/set-merged.ll create mode 100644 test/LTO/X86/symver-asm.ll create mode 100644 test/LTO/X86/triple-init.ll delete mode 100644 test/LTO/attrs.ll delete mode 100644 test/LTO/bcsection.ll delete mode 100644 test/LTO/cfi_endproc.ll delete mode 100644 test/LTO/current-section.ll delete mode 100644 test/LTO/diagnostic-handler-remarks.ll delete mode 100644 test/LTO/jump-table-type.ll delete mode 100644 test/LTO/keep-used-puts-during-instcombine.ll delete mode 100644 test/LTO/linkonce_odr_func.ll delete mode 100644 test/LTO/lit.local.cfg delete mode 100644 test/LTO/no-undefined-puts-when-implemented.ll delete mode 100644 test/LTO/private-symbol.ll delete mode 100644 test/LTO/runtime-library.ll delete mode 100644 test/LTO/symver-asm.ll delete mode 100644 test/LTO/triple-init.ll delete mode 100644 test/Linker/2006-06-15-GlobalVarAlignment.ll create mode 100644 test/Linker/Inputs/alignment.ll create mode 100644 test/Linker/Inputs/apple-version/1.ll create mode 100644 test/Linker/Inputs/apple-version/2.ll create mode 100644 test/Linker/Inputs/apple-version/3.ll create mode 100644 test/Linker/Inputs/apple-version/4.ll delete mode 100644 test/Linker/Inputs/comdat9.ll create mode 100644 test/Linker/Inputs/distinct.ll create mode 100644 test/Linker/Inputs/mdlocation.ll create mode 100644 test/Linker/Inputs/module-flags-dont-change-others.ll create mode 100644 test/Linker/Inputs/opaque.ll create mode 100644 test/Linker/Inputs/pr21374.ll create mode 100644 test/Linker/Inputs/replaced-function-matches-first-subprogram.ll create mode 100644 test/Linker/Inputs/targettriple-c.ll create mode 100644 test/Linker/Inputs/testlink.ll create mode 100644 test/Linker/Inputs/type-unique-alias.ll create mode 100644 test/Linker/Inputs/type-unique-dst-types2.ll create mode 100644 test/Linker/Inputs/type-unique-dst-types3.ll create mode 100644 test/Linker/Inputs/type-unique-name.ll create mode 100644 test/Linker/Inputs/type-unique-opaque.ll create mode 100644 test/Linker/Inputs/type-unique-unrelated2.ll create mode 100644 test/Linker/Inputs/type-unique-unrelated3.ll create mode 100644 test/Linker/Inputs/unique-fwd-decl-order.ll create mode 100644 test/Linker/alignment.ll create mode 100644 test/Linker/apple-version.ll create mode 100644 test/Linker/distinct-cycles.ll create mode 100644 test/Linker/distinct.ll create mode 100644 test/Linker/mdlocation.ll create mode 100644 test/Linker/module-flags-dont-change-others.ll create mode 100644 test/Linker/opaque.ll create mode 100644 test/Linker/pr21374.ll create mode 100644 test/Linker/pr21494.ll delete mode 100644 test/Linker/prefixdata.ll create mode 100644 test/Linker/prologuedata.ll create mode 100644 test/Linker/replaced-function-matches-first-subprogram.ll create mode 100644 test/Linker/testlink.ll delete mode 100644 test/Linker/testlink1.ll delete mode 100644 test/Linker/testlink2.ll create mode 100644 test/Linker/type-unique-alias.ll create mode 100644 test/Linker/type-unique-dst-types.ll create mode 100644 test/Linker/type-unique-name.ll create mode 100644 test/Linker/type-unique-opaque.ll create mode 100644 test/Linker/type-unique-src-type.ll create mode 100644 test/Linker/type-unique-unrelated.ll create mode 100644 test/Linker/unique-fwd-decl-order.ll create mode 100644 test/MC/ARM/Windows/invalid-relocation.s create mode 100644 test/MC/ARM/arm-elf-relocation-diagnostics.s create mode 100644 test/MC/ARM/arm-elf-relocations.s create mode 100644 test/MC/ARM/arm-load-store-multiple-deprecated.s create mode 100644 test/MC/ARM/cpu-test.s create mode 100644 test/MC/ARM/directive-fpu-diagnostics.s create mode 100644 test/MC/ARM/pr22395-2.s create mode 100644 test/MC/ARM/pr22395.s create mode 100644 test/MC/ARM/thumb-load-store-multiple.s create mode 100644 test/MC/ARM/thumb2-dsp-diag.s create mode 100644 test/MC/ARM/virtexts-arm.s create mode 100644 test/MC/ARM/virtexts-thumb.s delete mode 100644 test/MC/COFF/weak-symbol.ll create mode 100644 test/MC/Disassembler/ARM/invalid-virtexts.arm.txt create mode 100644 test/MC/Disassembler/ARM/virtexts-arm.txt create mode 100644 test/MC/Disassembler/ARM/virtexts-thumb.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_alu.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_perm.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_pred.txt create mode 100644 test/MC/Disassembler/Hexagon/cr.txt create mode 100644 test/MC/Disassembler/Hexagon/j.txt create mode 100644 test/MC/Disassembler/Hexagon/jr.txt create mode 100644 test/MC/Disassembler/Hexagon/ld.txt create mode 100644 test/MC/Disassembler/Hexagon/lit.local.cfg create mode 100644 test/MC/Disassembler/Hexagon/memop.txt create mode 100644 test/MC/Disassembler/Hexagon/nv_j.txt create mode 100644 test/MC/Disassembler/Hexagon/nv_st.txt create mode 100644 test/MC/Disassembler/Hexagon/st.txt create mode 100644 test/MC/Disassembler/Hexagon/system_user.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_alu.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_bit.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_complex.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_fp.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_mpy.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_perm.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_pred.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_shift.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-mips1-el.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-mips1.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-xfail.txt create mode 100644 test/MC/Disassembler/Mips/mips2/valid-mips2-el.txt create mode 100644 test/MC/Disassembler/Mips/mips2/valid-mips2.txt create mode 100644 test/MC/Disassembler/Mips/mips3/valid-mips3-el.txt create mode 100644 test/MC/Disassembler/Mips/mips3/valid-mips3.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-mips32-el.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-mips32.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-xfail-mips32.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-mips32r2-le.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-mips32r2.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-xfail-mips32r2.txt create mode 100644 test/MC/Disassembler/Mips/mips32r3/valid-mips32r3-le.txt create mode 100644 test/MC/Disassembler/Mips/mips32r3/valid-mips32r3.txt create mode 100644 test/MC/Disassembler/Mips/mips32r3/valid-xfail-mips32r3.txt create mode 100644 test/MC/Disassembler/Mips/mips32r5/valid-mips32r5-le.txt create mode 100644 test/MC/Disassembler/Mips/mips32r5/valid-mips32r5.txt create mode 100644 test/MC/Disassembler/Mips/mips32r5/valid-xfail-mips32r5.txt create mode 100644 test/MC/Disassembler/Mips/mips32r6/valid-mips32r6-el.txt create mode 100644 test/MC/Disassembler/Mips/mips32r6/valid-mips32r6.txt create mode 100644 test/MC/Disassembler/Mips/mips32r6/valid-xfail-mips32r6.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-mips4-el.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-mips4.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-xfail-mips4.txt create mode 100644 test/MC/Disassembler/Mips/mips64/valid-mips64-el.txt create mode 100644 test/MC/Disassembler/Mips/mips64/valid-mips64-xfail.txt create mode 100644 test/MC/Disassembler/Mips/mips64/valid-mips64.txt create mode 100644 test/MC/Disassembler/Mips/mips64r2/valid-mips64r2-el.txt create mode 100644 test/MC/Disassembler/Mips/mips64r2/valid-mips64r2.txt create mode 100644 test/MC/Disassembler/Mips/mips64r2/valid-xfail-mips64r2.txt create mode 100644 test/MC/Disassembler/Mips/mips64r3/valid-mips64r3-el.txt create mode 100644 test/MC/Disassembler/Mips/mips64r3/valid-mips64r3.txt create mode 100644 test/MC/Disassembler/Mips/mips64r3/valid-xfail-mips64r3.txt create mode 100644 test/MC/Disassembler/Mips/mips64r5/valid-mips64r5-el.txt create mode 100644 test/MC/Disassembler/Mips/mips64r5/valid-mips64r5.txt create mode 100644 test/MC/Disassembler/Mips/mips64r5/valid-xfail-mips64r5.txt create mode 100644 test/MC/Disassembler/Mips/mips64r6/valid-mips64r6-el.txt create mode 100644 test/MC/Disassembler/Mips/mips64r6/valid-mips64r6.txt create mode 100644 test/MC/Disassembler/Mips/mips64r6/valid-xfail-mips64r6.txt create mode 100644 test/MC/Disassembler/PowerPC/qpx.txt delete mode 100644 test/MC/Disassembler/X86/invalid-cmp-imm.txt create mode 100644 test/MC/ELF/cfi-large-model.s create mode 100644 test/MC/ELF/common-error1.s create mode 100644 test/MC/ELF/common-error2.s create mode 100644 test/MC/ELF/section-unique.s create mode 100644 test/MC/ELF/symver-msvc.s create mode 100644 test/MC/Hexagon/inst_add64.ll create mode 100644 test/MC/Hexagon/inst_and64.ll create mode 100644 test/MC/Hexagon/inst_aslh.ll create mode 100644 test/MC/Hexagon/inst_asrh.ll create mode 100644 test/MC/Hexagon/inst_cmp_eq.ll create mode 100644 test/MC/Hexagon/inst_cmp_eqi.ll create mode 100644 test/MC/Hexagon/inst_cmp_gt.ll create mode 100644 test/MC/Hexagon/inst_cmp_gti.ll create mode 100644 test/MC/Hexagon/inst_cmp_lt.ll create mode 100644 test/MC/Hexagon/inst_cmp_ugt.ll create mode 100644 test/MC/Hexagon/inst_cmp_ugti.ll create mode 100644 test/MC/Hexagon/inst_cmp_ult.ll create mode 100644 test/MC/Hexagon/inst_or64.ll create mode 100644 test/MC/Hexagon/inst_select.ll create mode 100644 test/MC/Hexagon/inst_sub64.ll create mode 100644 test/MC/Hexagon/inst_sxtb.ll create mode 100644 test/MC/Hexagon/inst_sxth.ll create mode 100644 test/MC/Hexagon/inst_xor64.ll create mode 100644 test/MC/Hexagon/inst_zxtb.ll create mode 100644 test/MC/Hexagon/inst_zxth.ll create mode 100644 test/MC/MachO/AArch64/cfstring.s create mode 100644 test/MC/MachO/AArch64/classrefs.s create mode 100644 test/MC/MachO/AArch64/mergeable.s create mode 100644 test/MC/MachO/AArch64/reloc-crash.s create mode 100644 test/MC/MachO/AArch64/reloc-crash2.s create mode 100644 test/MC/MachO/x86_64-mergeable.s create mode 100644 test/MC/Mips/micromips-branch-fixup.s delete mode 100644 test/MC/Mips/micromips-branch16.s create mode 100644 test/MC/Mips/micromips-func-addr.s create mode 100644 test/MC/Mips/mips32r3/abiflags.s create mode 100644 test/MC/Mips/mips32r3/invalid-mips64r2.s create mode 100644 test/MC/Mips/mips32r3/invalid.s create mode 100644 test/MC/Mips/mips32r3/valid-xfail.s create mode 100644 test/MC/Mips/mips32r3/valid.s create mode 100644 test/MC/Mips/mips32r5/abiflags.s create mode 100644 test/MC/Mips/mips32r5/invalid-mips64r2.s create mode 100644 test/MC/Mips/mips32r5/invalid.s create mode 100644 test/MC/Mips/mips32r5/valid-xfail.s create mode 100644 test/MC/Mips/mips32r5/valid.s create mode 100644 test/MC/Mips/mips64r3/abi-bad.s create mode 100644 test/MC/Mips/mips64r3/abiflags.s create mode 100644 test/MC/Mips/mips64r3/invalid.s create mode 100644 test/MC/Mips/mips64r3/valid-xfail.s create mode 100644 test/MC/Mips/mips64r3/valid.s create mode 100644 test/MC/Mips/mips64r5/abi-bad.s create mode 100644 test/MC/Mips/mips64r5/abiflags.s create mode 100644 test/MC/Mips/mips64r5/invalid.s create mode 100644 test/MC/Mips/mips64r5/valid-xfail.s create mode 100644 test/MC/Mips/mips64r5/valid.s create mode 100644 test/MC/Mips/set-at-noat-bad-syntax.s create mode 100644 test/MC/PowerPC/qpx.s create mode 100644 test/MC/SystemZ/fixups.s create mode 100644 test/MC/X86/avx512bw-encoding.s create mode 100644 test/MC/X86/avx512vl-encoding.s create mode 100644 test/MC/X86/compact-unwind.s create mode 100644 test/MC/X86/cstexpr-gotpcrel.ll create mode 100644 test/MC/X86/i386-darwin-frame-register.ll create mode 100644 test/MC/X86/intel-syntax-unsized-memory.s create mode 100644 test/MC/X86/validate-inst-att.s create mode 100644 test/MC/X86/validate-inst-intel.s create mode 100644 test/Object/Inputs/archive-test.a-irix6-mips64el create mode 100644 test/Object/Inputs/macho-invalid-bad-symbol-index create mode 100644 test/Object/Inputs/macho-invalid-getsection-index create mode 100644 test/Object/Inputs/macho-invalid-no-size-for-sections create mode 100644 test/Object/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentName create mode 100644 test/Object/Inputs/macho-invalid-section-index-getSectionRawName create mode 100644 test/Object/Inputs/macho-invalid-symbol-name-past-eof create mode 100644 test/Object/Inputs/macho-invalid-too-small-load-command create mode 100644 test/Object/Inputs/macho-invalid-too-small-segment-load-command create mode 100644 test/Object/Inputs/macho-invalid-zero-ncmds create mode 100755 test/Object/Inputs/macho-no-exports.dylib create mode 100755 test/Object/Inputs/macho-rpath-x86_64 create mode 100644 test/Object/Inputs/macho64-invalid-getsection-index create mode 100644 test/Object/Inputs/macho64-invalid-incomplete-load-command create mode 100644 test/Object/Inputs/macho64-invalid-no-size-for-sections create mode 100644 test/Object/Inputs/macho64-invalid-too-small-load-command create mode 100644 test/Object/Inputs/macho64-invalid-too-small-segment-load-command create mode 100755 test/Object/Inputs/micro-mips.elf-mipsel create mode 100644 test/Object/Inputs/sectionGroup.elf.x86-64 create mode 100644 test/Object/Inputs/thin.a create mode 100644 test/Object/Mips/elf-mips64-rel.yaml create mode 100644 test/Object/Mips/objdump-micro-mips.test create mode 100644 test/Object/elf-unknown-type.test create mode 100644 test/Object/macho-invalid.test create mode 100644 test/Object/nm-irix6.test create mode 100644 test/Object/obj2yaml-sectiongroup.test create mode 100644 test/Object/objdump-export-list.test create mode 100644 test/Other/Inputs/utf8-bom-response create mode 100644 test/Other/Inputs/utf8-response create mode 100644 test/Transforms/BDCE/basic.ll create mode 100644 test/Transforms/BDCE/dce-pure.ll create mode 100644 test/Transforms/BDCE/order.ll create mode 100644 test/Transforms/CodeGenPrepare/statepoint-relocate.ll create mode 100644 test/Transforms/ConstProp/InsertElement.ll create mode 100644 test/Transforms/CorrelatedValuePropagation/icmp.ll create mode 100644 test/Transforms/DeadArgElim/aggregates.ll delete mode 100644 test/Transforms/DebugIR/crash.ll delete mode 100644 test/Transforms/DebugIR/exception.ll delete mode 100644 test/Transforms/DebugIR/function.ll delete mode 100644 test/Transforms/DebugIR/simple-addrspace.ll delete mode 100644 test/Transforms/DebugIR/simple.ll delete mode 100644 test/Transforms/DebugIR/struct.ll delete mode 100644 test/Transforms/DebugIR/vector.ll create mode 100644 test/Transforms/EarlyCSE/AArch64/intrinsics.ll create mode 100644 test/Transforms/EarlyCSE/AArch64/lit.local.cfg create mode 100644 test/Transforms/GCOVProfiling/return-block.ll create mode 100644 test/Transforms/GVN/load-from-unreachable-predecessor.ll create mode 100644 test/Transforms/GVN/pre-gep-load.ll create mode 100644 test/Transforms/GVN/pre-no-cost-phi.ll create mode 100644 test/Transforms/GVN/volatile.ll create mode 100644 test/Transforms/IRCE/bug-mismatched-types.ll create mode 100644 test/Transforms/IRCE/decrementing-loop.ll create mode 100644 test/Transforms/IRCE/low-becount.ll create mode 100644 test/Transforms/IRCE/multiple-access-no-preloop.ll create mode 100644 test/Transforms/IRCE/not-likely-taken.ll create mode 100644 test/Transforms/IRCE/single-access-no-preloop.ll create mode 100644 test/Transforms/IRCE/single-access-with-preloop.ll create mode 100644 test/Transforms/IRCE/unhandled.ll create mode 100644 test/Transforms/IRCE/with-parent-loops.ll create mode 100644 test/Transforms/IndVarSimplify/backedge-on-min-max.ll create mode 100644 test/Transforms/IndVarSimplify/pr22222.ll create mode 100644 test/Transforms/IndVarSimplify/strengthen-overflow.ll create mode 100644 test/Transforms/Inline/alloca-dbgdeclare.ll create mode 100644 test/Transforms/Inline/debug-info-duplicate-calls.ll create mode 100644 test/Transforms/Inline/inline-fast-math-flags.ll create mode 100644 test/Transforms/Inline/inline-fp.ll create mode 100644 test/Transforms/Inline/inline-indirect.ll create mode 100644 test/Transforms/Inline/inline_dbg_declare.ll create mode 100644 test/Transforms/InstCombine/alias-recursion.ll create mode 100644 test/Transforms/InstCombine/aligned-altivec.ll create mode 100644 test/Transforms/InstCombine/aligned-qpx.ll create mode 100644 test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll create mode 100644 test/Transforms/InstCombine/gc.relocate.ll create mode 100644 test/Transforms/InstCombine/gep-sext.ll create mode 100644 test/Transforms/InstCombine/max-of-nots.ll create mode 100644 test/Transforms/InstCombine/mem-gep-zidx.ll create mode 100644 test/Transforms/InstCombine/pr21199.ll create mode 100644 test/Transforms/InstCombine/pr21210.ll create mode 100644 test/Transforms/InstCombine/pr21651.ll create mode 100644 test/Transforms/InstCombine/pr21891.ll create mode 100644 test/Transforms/InstCombine/range-check.ll create mode 100644 test/Transforms/InstCombine/select-cmp-br.ll create mode 100644 test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll create mode 100644 test/Transforms/InstCombine/statepoint.ll create mode 100644 test/Transforms/InstCombine/type_pun.ll create mode 100644 test/Transforms/InstCombine/unordered-fcmp-select.ll create mode 100644 test/Transforms/InstMerge/st_sink_barrier_call.ll create mode 100644 test/Transforms/InstMerge/st_sink_bugfix_22613.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_call.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_load.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_store.ll create mode 100644 test/Transforms/InstMerge/st_sink_two_stores.ll create mode 100644 test/Transforms/InstMerge/st_sink_with_barrier.ll create mode 100644 test/Transforms/InstSimplify/floating-point-compare.ll create mode 100644 test/Transforms/InstSimplify/load.ll create mode 100644 test/Transforms/InstSimplify/noalias-ptr.ll create mode 100644 test/Transforms/InstSimplify/select.ll create mode 100644 test/Transforms/JumpThreading/conservative-lvi.ll create mode 100644 test/Transforms/JumpThreading/pr22086.ll create mode 100644 test/Transforms/LICM/constexpr.ll create mode 100644 test/Transforms/LICM/preheader-safe.ll create mode 100644 test/Transforms/LoopRotate/pr22337.ll create mode 100644 test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll create mode 100644 test/Transforms/LoopUnroll/full-unroll-heuristics.ll create mode 100644 test/Transforms/LoopVectorize/AArch64/arbitrary-induction-step.ll create mode 100644 test/Transforms/LoopVectorize/PowerPC/small-loop-rdx.ll create mode 100644 test/Transforms/LoopVectorize/X86/masked_load_store.ll create mode 100644 test/Transforms/LoopVectorize/loop-form.ll create mode 100644 test/Transforms/LoopVectorize/loop-vect-memdep.ll create mode 100644 test/Transforms/LowerBitSets/constant.ll create mode 100644 test/Transforms/LowerBitSets/layout.ll create mode 100644 test/Transforms/LowerBitSets/simple.ll create mode 100644 test/Transforms/LowerBitSets/single-offset.ll create mode 100644 test/Transforms/LowerSwitch/fold-popular-case-to-unreachable-default.ll create mode 100644 test/Transforms/MemCpyOpt/callslot_aa.ll create mode 100644 test/Transforms/PlaceSafepoints/basic.ll create mode 100644 test/Transforms/PlaceSafepoints/call-in-loop.ll create mode 100644 test/Transforms/PlaceSafepoints/finite-loops.ll create mode 100644 test/Transforms/PlaceSafepoints/invokes.ll create mode 100644 test/Transforms/PlaceSafepoints/split-backedge.ll delete mode 100644 test/Transforms/PruneEH/2003-11-21-PHIUpdate.ll create mode 100644 test/Transforms/PruneEH/seh-nounwind.ll create mode 100644 test/Transforms/Reassociate/crash2.ll create mode 100644 test/Transforms/Reassociate/min_int.ll create mode 100644 test/Transforms/RewriteStatepointsForGC/basics.ll create mode 100644 test/Transforms/SLPVectorizer/X86/atomics.ll create mode 100644 test/Transforms/SLPVectorizer/X86/bad_types.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_cmpop.ll create mode 100644 test/Transforms/SimplifyCFG/AArch64/lit.local.cfg create mode 100644 test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll create mode 100644 test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll create mode 100644 test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg create mode 100644 test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll create mode 100644 test/Transforms/SimplifyCFG/R600/lit.local.cfg create mode 100644 test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll create mode 100644 test/Transforms/SimplifyCFG/clamp.ll create mode 100644 test/Transforms/SimplifyCFG/seh-nounwind.ll create mode 100644 test/Transforms/SimplifyCFG/switch-range-to-icmp.ll create mode 100644 test/Transforms/SimplifyCFG/switch-to-br.ll delete mode 100644 test/Transforms/SimplifyCFG/trivial-throw.ll create mode 100644 test/Transforms/StraightLineStrengthReduce/slsr.ll create mode 100644 test/Transforms/StructurizeCFG/nested-loop-order.ll create mode 100644 test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll create mode 100644 test/Transforms/StructurizeCFG/post-order-traversal-bug.ll create mode 100644 test/Transforms/Util/combine-alias-scope-metadata.ll create mode 100644 test/Verifier/comdat3.ll create mode 100644 test/Verifier/frameallocate.ll create mode 100644 test/Verifier/ident-meta4.ll create mode 100644 test/Verifier/module-flags-2.ll create mode 100644 test/Verifier/module-flags-3.ll create mode 100644 test/Verifier/statepoint.ll create mode 100755 test/tools/dsymutil/Inputs/basic-archive.macho.x86_64 create mode 100755 test/tools/dsymutil/Inputs/basic-lto.macho.x86_64 create mode 100644 test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o create mode 100755 test/tools/dsymutil/Inputs/basic.macho.x86_64 create mode 100644 test/tools/dsymutil/Inputs/basic1.c create mode 100644 test/tools/dsymutil/Inputs/basic1.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/basic2.c create mode 100644 test/tools/dsymutil/Inputs/basic2.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/basic3.c create mode 100644 test/tools/dsymutil/Inputs/basic3.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/libbasic.a create mode 100644 test/tools/dsymutil/basic-linking.test create mode 100644 test/tools/dsymutil/debug-map-parsing.test create mode 100644 test/tools/gold/Inputs/drop-debug.bc create mode 100644 test/tools/gold/coff.ll create mode 100644 test/tools/gold/drop-debug.ll create mode 100644 test/tools/gold/no-map-whole-file.ll create mode 100644 test/tools/gold/stats.ll create mode 100644 test/tools/llvm-objdump/AArch64/Inputs/link-opt-hints.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/macho-link-opt-hints.test create mode 100644 test/tools/llvm-objdump/AArch64/macho-private-headers.test create mode 100644 test/tools/llvm-objdump/ARM/Inputs/data-in-code.macho-arm create mode 100644 test/tools/llvm-objdump/ARM/macho-data-in-code.test create mode 100644 test/tools/llvm-objdump/ARM/macho-private-headers.test create mode 100644 test/tools/llvm-objdump/Inputs/common-symbol-elf create mode 100644 test/tools/llvm-objdump/Inputs/proc-specific-section-elf create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibModInit.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibRoutines.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubClient.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubFramework.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubLibrary.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubUmbrella.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/exeThread.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/linkerOption.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/macho-universal-archive.x86_64.i386 create mode 100755 test/tools/llvm-objdump/X86/Inputs/macho-universal.x86_64.i386 create mode 100644 test/tools/llvm-objdump/X86/macho-archive-headers.test create mode 100644 test/tools/llvm-objdump/X86/macho-cstring-dump.test create mode 100644 test/tools/llvm-objdump/X86/macho-indirect-symbols.test create mode 100644 test/tools/llvm-objdump/X86/macho-literal-pointers-i386.test create mode 100644 test/tools/llvm-objdump/X86/macho-literal-pointers-x86_64.test create mode 100644 test/tools/llvm-objdump/X86/macho-literals.test create mode 100644 test/tools/llvm-objdump/X86/macho-nontext-disasm.test create mode 100644 test/tools/llvm-objdump/X86/macho-relocations.test create mode 100644 test/tools/llvm-objdump/X86/macho-section-contents.test create mode 100644 test/tools/llvm-objdump/X86/macho-section-headers.test create mode 100644 test/tools/llvm-objdump/X86/macho-section.test create mode 100644 test/tools/llvm-objdump/X86/macho-symbol-table.test create mode 100644 test/tools/llvm-objdump/X86/macho-universal-x86_64.i386.test create mode 100644 test/tools/llvm-objdump/X86/macho-unwind-info.test create mode 100644 test/tools/llvm-objdump/common-symbol-elf.test create mode 100644 test/tools/llvm-objdump/proc-specific-section-elf.test create mode 100644 test/tools/llvm-readobj/ARM/attribute-0.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-1.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-10.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-11.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-12.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-13.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-136.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-14.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-15.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-2.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-3.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-4.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-5.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-6.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-7.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-8.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-9.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-A.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-M.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-R.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-S.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-conformance-1.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-conformance-2.s delete mode 100644 test/tools/llvm-readobj/ARM/attributes.s create mode 100755 test/tools/llvm-readobj/Inputs/export-arm.dll create mode 100755 test/tools/llvm-readobj/Inputs/export-x64.dll create mode 100755 test/tools/llvm-readobj/Inputs/export-x86.dll create mode 100644 test/tools/llvm-readobj/Inputs/relocs-no-symtab.obj.coff-i386 create mode 100755 test/tools/llvm-readobj/Inputs/trivial.exe.coff-arm create mode 100644 test/tools/llvm-readobj/coff-arm-baserelocs.test create mode 100644 test/tools/llvm-readobj/coff-exports.test create mode 100644 tools/dsymutil/BinaryHolder.cpp create mode 100644 tools/dsymutil/BinaryHolder.h create mode 100644 tools/dsymutil/CMakeLists.txt create mode 100644 tools/dsymutil/DebugMap.cpp create mode 100644 tools/dsymutil/DebugMap.h create mode 100644 tools/dsymutil/DwarfLinker.cpp create mode 100644 tools/dsymutil/LLVMBuild.txt create mode 100644 tools/dsymutil/MachODebugMapParser.cpp create mode 100644 tools/dsymutil/Makefile create mode 100644 tools/dsymutil/dsymutil.cpp create mode 100644 tools/dsymutil/dsymutil.h create mode 100644 tools/llvm-ar/install_symlink.cmake create mode 100644 tools/llvm-c-test/metadata.c delete mode 100644 tools/llvm-cov/CoverageSummary.cpp delete mode 100644 tools/llvm-cov/CoverageSummary.h create mode 100644 tools/llvm-pdbdump/CMakeLists.txt create mode 100644 tools/llvm-pdbdump/ClassDefinitionDumper.cpp create mode 100644 tools/llvm-pdbdump/ClassDefinitionDumper.h create mode 100644 tools/llvm-pdbdump/CompilandDumper.cpp create mode 100644 tools/llvm-pdbdump/CompilandDumper.h create mode 100644 tools/llvm-pdbdump/FunctionDumper.cpp create mode 100644 tools/llvm-pdbdump/FunctionDumper.h create mode 100644 tools/llvm-pdbdump/LLVMBuild.txt create mode 100644 tools/llvm-pdbdump/Makefile create mode 100644 tools/llvm-pdbdump/TypeDumper.cpp create mode 100644 tools/llvm-pdbdump/TypeDumper.h create mode 100644 tools/llvm-pdbdump/TypedefDumper.cpp create mode 100644 tools/llvm-pdbdump/TypedefDumper.h create mode 100644 tools/llvm-pdbdump/VariableDumper.cpp create mode 100644 tools/llvm-pdbdump/VariableDumper.h create mode 100644 tools/llvm-pdbdump/llvm-pdbdump.cpp create mode 100644 tools/llvm-pdbdump/llvm-pdbdump.h create mode 100644 unittests/DebugInfo/DWARF/CMakeLists.txt create mode 100644 unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp create mode 100644 unittests/DebugInfo/DWARF/Makefile delete mode 100644 unittests/DebugInfo/DWARFFormValueTest.cpp create mode 100644 unittests/DebugInfo/PDB/CMakeLists.txt create mode 100644 unittests/DebugInfo/PDB/Makefile create mode 100644 unittests/DebugInfo/PDB/PDBApiTest.cpp create mode 100644 unittests/ExecutionEngine/Orc/CMakeLists.txt create mode 100644 unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp create mode 100644 unittests/ExecutionEngine/Orc/Makefile delete mode 100644 unittests/IR/LeakDetectorTest.cpp delete mode 100644 unittests/MC/Hexagon/CMakeLists.txt delete mode 100644 unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp create mode 100644 unittests/ProfileData/CMakeLists.txt create mode 100644 unittests/ProfileData/CoverageMappingTest.cpp create mode 100644 unittests/ProfileData/InstrProfTest.cpp create mode 100644 unittests/ProfileData/Makefile create mode 100644 unittests/Support/DwarfTest.cpp create mode 100644 unittests/Support/EndianStreamTest.cpp create mode 100644 unittests/Support/StreamingMemoryObject.cpp delete mode 100644 unittests/Transforms/DebugIR/CMakeLists.txt delete mode 100644 unittests/Transforms/DebugIR/DebugIR.cpp delete mode 100644 unittests/Transforms/DebugIR/Makefile create mode 100644 unittests/Transforms/IPO/CMakeLists.txt create mode 100644 unittests/Transforms/IPO/LowerBitSets.cpp create mode 100644 unittests/Transforms/IPO/Makefile create mode 100755 utils/update_llc_test_checks.py diff --git a/.gitignore b/.gitignore index e806c2c..7109373 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ # Byte compiled python modules. *.pyc # vim swap files -.*.swp +.*.sw? .sw? #OS X specific files. .DS_store @@ -24,6 +24,13 @@ #==============================================================================# # Explicit files to ignore (only matches one). #==============================================================================# +# Various tag programs +/tags +/TAGS +/GPATH +/GRTAGS +/GSYMS +/GTAGS .gitusers autom4te.cache cscope.files @@ -45,6 +52,8 @@ tools/clang tools/lldb # lld, which is tracked independently. tools/lld +# llgo, which is tracked independently. +tools/llgo # Polly, which is tracked independently. tools/polly # Sphinx build tree, if building in-source dir. diff --git a/Android.mk b/Android.mk index 1f4421c..bc628e1 100644 --- a/Android.mk +++ b/Android.mk @@ -14,11 +14,13 @@ subdirs := \ lib/ExecutionEngine \ lib/ExecutionEngine/RuntimeDyld \ lib/ExecutionEngine/MCJIT \ + lib/ExecutionEngine/Orc \ lib/ExecutionEngine/Interpreter \ lib/CodeGen \ lib/CodeGen/AsmPrinter \ lib/CodeGen/SelectionDAG \ - lib/DebugInfo \ + lib/DebugInfo/DWARF \ + lib/DebugInfo/PDB \ lib/IR \ lib/IRReader \ lib/Linker \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6691189..ed7aeb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 2.8.8) +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No build type selected, default to Debug") + set(CMAKE_BUILD_TYPE "Debug") +endif() + # FIXME: It may be removed when we use 2.8.12. if(CMAKE_VERSION VERSION_LESS 2.8.12) # Invalidate a couple of keywords. @@ -16,6 +21,15 @@ else() endif() endif() +if (POLICY CMP0051) + # CMake 3.1 and higher include generator expressions of the form + # $ in the SOURCES property. These need to be + # stripped everywhere that access the SOURCES property, so we just + # defer to the OLD behavior of not including generator expressions + # in the output for now. + cmake_policy(SET CMP0051 OLD) +endif() + if(CMAKE_VERSION VERSION_LESS 3.1.20141117) set(cmake_3_2_USES_TERMINAL) else() @@ -47,8 +61,9 @@ set(CMAKE_MODULE_PATH ) set(LLVM_VERSION_MAJOR 3) -set(LLVM_VERSION_MINOR 6) +set(LLVM_VERSION_MINOR 7) set(LLVM_VERSION_PATCH 0) +set(LLVM_VERSION_SUFFIX svn) if (NOT PACKAGE_VERSION) set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}svn") @@ -96,6 +111,9 @@ if(WIN32 AND NOT UNIX) "ExecWait '$INSTDIR/tools/msbuild/install.bat'") set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "ExecWait '$INSTDIR/tools/msbuild/uninstall.bat'") + if( CMAKE_CL_64 ) + set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") + endif() endif() include(CPack) @@ -132,9 +150,11 @@ endif() string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) +set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) + # They are used as destination of target generators. set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) -set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) +set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) if(WIN32 OR CYGWIN) # DLL platform -- put DLLs into bin. set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) @@ -151,7 +171,6 @@ set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) # --prefix set(LLVM_EXAMPLES_BINARY_DIR ${LLVM_BINARY_DIR}/examples) set(LLVM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) -set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) set(LLVM_ALL_TARGETS AArch64 @@ -324,6 +343,10 @@ option (LLVM_BUILD_EXTERNAL_COMPILER_RT "Build compiler-rt as an external project." OFF) option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" OFF) +option(LLVM_DISABLE_LLVM_DYLIB_ATEXIT "Disable llvm-shlib's atexit destructors." ON) +if(LLVM_DISABLE_LLVM_DYLIB_ATEXIT) + set(DISABLE_LLVM_DYLIB_ATEXIT 1) +endif() # All options referred to from HandleLLVMOptions have to be specified # BEFORE this include, otherwise options will not be correctly set on @@ -339,7 +362,9 @@ set(TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}") include(HandleLLVMOptions) # Verify that we can find a Python 2 interpreter. Python 3 is unsupported. -set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) +# FIXME: We should support systems with only Python 3, but that requires work +# on LLDB. +set(Python_ADDITIONAL_VERSIONS 2.7) include(FindPythonInterp) if( NOT PYTHONINTERP_FOUND ) message(FATAL_ERROR @@ -348,6 +373,10 @@ if( NOT PYTHONINTERP_FOUND ) Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") endif() +if( ${PYTHON_VERSION_STRING} VERSION_LESS 2.7 ) + message(FATAL_ERROR "Python 2.7 or newer is required") +endif() + ###### # LLVMBuild Integration # @@ -473,8 +502,8 @@ configure_file( # They are not referenced. See set_output_directory(). set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/bin ) -set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) -set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) if (APPLE) @@ -482,7 +511,7 @@ if (APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../lib") else(UNIX) if(NOT DEFINED CMAKE_INSTALL_RPATH) - set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib") + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}") if (${CMAKE_SYSTEM_NAME} MATCHES FreeBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,origin") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,origin") @@ -561,6 +590,12 @@ if(LLVM_INCLUDE_TESTS) add_subdirectory(utils/unittest) endif() +foreach( binding ${LLVM_BINDINGS_LIST} ) + if( EXISTS "${LLVM_MAIN_SRC_DIR}/bindings/${binding}/CMakeLists.txt" ) + add_subdirectory(bindings/${binding}) + endif() +endforeach() + add_subdirectory(projects) if(WITH_POLLY) @@ -610,6 +645,7 @@ add_subdirectory(cmake/modules) if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY include/llvm include/llvm-c DESTINATION include + COMPONENT llvm-headers FILES_MATCHING PATTERN "*.def" PATTERN "*.h" @@ -621,6 +657,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY ${LLVM_INCLUDE_DIR}/llvm DESTINATION include + COMPONENT llvm-headers FILES_MATCHING PATTERN "*.def" PATTERN "*.h" @@ -631,4 +668,12 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) PATTERN "config.h" EXCLUDE PATTERN ".svn" EXCLUDE ) + + if (NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(installhdrs + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=llvm-headers + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() endif() diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index 071f6c8..b674756 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -20,6 +20,10 @@ N: Rafael Avila de Espindola E: rafael.espindola@gmail.com D: Gold plugin (tools/gold/*) +N: Justin Bogner +E: mail@justinbogner.com +D: InstrProfiling and related parts of ProfileData + N: Chandler Carruth E: chandlerc@gmail.com E: chandlerc@google.com @@ -29,10 +33,6 @@ N: Evan Cheng E: evan.cheng@apple.com D: ARM target, parts of code generator not covered by someone else -N: Renato Golin -E: renato.golin@linaro.org -D: ARM Linux support - N: Eric Christopher E: echristo@gmail.com D: Debug Information, autotools/configure/make build, inline assembly @@ -41,18 +41,30 @@ N: Greg Clayton E: gclayton@apple.com D: LLDB +N: Marshall Clow +E: mclow.lists@gmail.com +D: libc++ + N: Peter Collingbourne E: peter@pcc.me.uk -D: libclc +D: llgo N: Anshuman Dasgupta E: adasgupt@codeaurora.org D: Hexagon Backend +N: Duncan P. N. Exon Smith +E: dexonsmith@apple.com +D: Branch weights and BlockFrequencyInfo + N: Hal Finkel E: hfinkel@anl.gov D: BBVectorize, the loop reroller, alias analysis and the PowerPC target +N: Renato Golin +E: renato.golin@linaro.org +D: ARM Linux support + N: Venkatraman Govindaraju E: venkatra@cs.wisc.edu D: Sparc Backend (lib/Target/Sparc/*) @@ -65,10 +77,6 @@ N: James Grosbach E: grosbach@apple.com D: MC layer -N: Marshall Clow -E: mclow.lists@gmail.com -D: libc++ - N: Justin Holewinski E: jholewinski@nvidia.com D: NVPTX Target (lib/Target/NVPTX/*) @@ -102,6 +110,10 @@ N: Tim Northover E: t.p.northover@gmail.com D: AArch64 backend +N: Diego Novillo +E: dnovillo@google.com +D: SampleProfile and related parts of ProfileData + N: Jakob Olesen E: stoklund@2pi.dk D: Register allocators and TableGen @@ -114,6 +126,10 @@ N: Chad Rosier E: mcrosier@codeaurora.org D: Fast-Isel +N: Alex Rosenberg +E: alexr@leftfield.org +D: Sony PlayStation®4 support + N: Nadav Rotem E: nrotem@apple.com D: X86 Backend, Loop Vectorizer @@ -122,10 +138,6 @@ 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 - N: Duncan Sands E: baldrick@free.fr D: DragonEgg @@ -138,10 +150,14 @@ N: Michael Spencer E: bigcheesegs@gmail.com D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size +N: Alexei Starovoitov +E: alexei.starovoitov@gmail.com +D: BPF backend + N: Tom Stellard E: thomas.stellard@amd.com E: mesa-dev@lists.freedesktop.org -D: Release manager for the 3.5 branch, R600 Backend +D: Release manager for the 3.5 branch, R600 Backend, libclc N: Evgeniy Stepanov E: eugenis@google.com @@ -151,6 +167,10 @@ N: Andrew Trick E: atrick@apple.com D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling +N: Ulrich Weigand +E: uweigand@de.ibm.com +D: SystemZ Backend + N: Bill Wendling E: isanbard@gmail.com D: libLTO, IR Linker diff --git a/README.txt b/README.txt index 193330f..6358a06 100644 --- a/README.txt +++ b/README.txt @@ -1,8 +1,8 @@ Low Level Virtual Machine (LLVM) ================================ -This directory and its subdirectories contain source code for the Low Level -Virtual Machine, a toolkit for the construction of highly optimized compilers, +This directory and its subdirectories contain source code for LLVM, +a toolkit for the construction of highly optimized compilers, optimizers, and runtime environments. LLVM is open source software. You may freely distribute it under the terms of diff --git a/autoconf/config.sub b/autoconf/config.sub index 673d62b..2583c90 100755 --- a/autoconf/config.sub +++ b/autoconf/config.sub @@ -1354,7 +1354,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -bitrig*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1489,6 +1489,8 @@ case $os in ;; -nacl*) ;; + -ps4) + ;; -none) ;; *) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index c998dd5..e0bc783 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -32,10 +32,10 @@ dnl===-----------------------------------------------------------------------=== dnl Initialize autoconf and define the package name, version number and dnl address for reporting bugs. -AC_INIT([LLVM],[3.6.0svn],[http://llvm.org/bugs/]) +AC_INIT([LLVM],[3.7.0svn],[http://llvm.org/bugs/]) LLVM_VERSION_MAJOR=3 -LLVM_VERSION_MINOR=6 +LLVM_VERSION_MINOR=7 LLVM_VERSION_PATCH=0 LLVM_VERSION_SUFFIX=svn @@ -267,6 +267,11 @@ AC_CACHE_CHECK([type of operating system we're going to host on], llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="DragonFly" llvm_cv_platform_type="Unix" ;; + *-*-bitrig*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Bitrig" + llvm_cv_platform_type="Unix" ;; *-*-hpux*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -347,6 +352,8 @@ AC_CACHE_CHECK([type of operating system we're going to target], llvm_cv_target_os_type="NetBSD" ;; *-*-dragonfly*) llvm_cv_target_os_type="DragonFly" ;; + *-*-bitrig*) + llvm_cv_target_os_type="Bitrig" ;; *-*-hpux*) llvm_cv_target_os_type="HP-UX" ;; *-*-interix*) @@ -369,6 +376,8 @@ AC_CACHE_CHECK([type of operating system we're going to target], llvm_cv_target_os_type="NativeClient" ;; *-unknown-eabi*) llvm_cv_target_os_type="Freestanding" ;; + *-*-ps4) + llvm_cv_target_os_type="PS4" ;; *) llvm_cv_target_os_type="Unknown" ;; esac]) @@ -1533,11 +1542,11 @@ AC_ARG_WITH(oprofile, AC_SEARCH_LIBS(bfd_init, bfd, [], []) AC_SEARCH_LIBS(op_open_agent, opagent, [], [ echo "Error! You need to have libopagent around." - exit -1 + exit 1 ]) AC_CHECK_HEADER([opagent.h], [], [ echo "Error! You need to have opagent.h around." - exit -1 + exit 1 ]) fi ;; *) @@ -1714,7 +1723,9 @@ if test "$llvm_cv_os_type" = "MingW" ; then AC_CHECK_LIB(gcc,_alloca,AC_DEFINE([HAVE__ALLOCA],[1],[Have host's _alloca])) AC_CHECK_LIB(gcc,__alloca,AC_DEFINE([HAVE___ALLOCA],[1],[Have host's __alloca])) AC_CHECK_LIB(gcc,__chkstk,AC_DEFINE([HAVE___CHKSTK],[1],[Have host's __chkstk])) + AC_CHECK_LIB(gcc,__chkstk_ms,AC_DEFINE([HAVE___CHKSTK_MS],[1],[Have host's __chkstk_ms])) AC_CHECK_LIB(gcc,___chkstk,AC_DEFINE([HAVE____CHKSTK],[1],[Have host's ___chkstk])) + AC_CHECK_LIB(gcc,___chkstk_ms,AC_DEFINE([HAVE____CHKSTK_MS],[1],[Have host's ___chkstk_ms])) AC_CHECK_LIB(gcc,__ashldi3,AC_DEFINE([HAVE___ASHLDI3],[1],[Have host's __ashldi3])) AC_CHECK_LIB(gcc,__ashrdi3,AC_DEFINE([HAVE___ASHRDI3],[1],[Have host's __ashrdi3])) @@ -2017,6 +2028,11 @@ if test "${clang_src_root}" = ""; then clang_src_root="$srcdir/tools/clang" fi if test -f ${clang_src_root}/README.txt; then + dnl Clang supports build systems which use the multilib libdir suffix. + dnl The autoconf system doesn't support this so stub out that variable. + AC_DEFINE_UNQUOTED(CLANG_LIBDIR_SUFFIX,"", + [Multilib suffix for libdir.]) + dnl Use variables to stay under 80 columns. configh="include/clang/Config/config.h" doxy="docs/doxygen.cfg" diff --git a/bindings/go/llvm/DIBuilderBindings.cpp b/bindings/go/llvm/DIBuilderBindings.cpp index 94fa96f..a7d75a3 100644 --- a/bindings/go/llvm/DIBuilderBindings.cpp +++ b/bindings/go/llvm/DIBuilderBindings.cpp @@ -12,21 +12,21 @@ //===----------------------------------------------------------------------===// #include "DIBuilderBindings.h" - -#include "llvm/IR/Module.h" +#include "IRBindings.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" using namespace llvm; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef) + namespace { -template -T unwrapDI(LLVMValueRef v) { +template T unwrapDI(LLVMMetadataRef v) { return v ? T(unwrap(v)) : T(); } } -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef) - LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef mref) { Module *m = unwrap(mref); return wrap(new DIBuilder(*m)); @@ -39,49 +39,50 @@ void LLVMDIBuilderDestroy(LLVMDIBuilderRef dref) { void LLVMDIBuilderFinalize(LLVMDIBuilderRef dref) { unwrap(dref)->finalize(); } -LLVMValueRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref, - unsigned Lang, const char *File, - const char *Dir, - const char *Producer, int Optimized, - const char *Flags, - unsigned RuntimeVersion) { +LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref, + unsigned Lang, const char *File, + const char *Dir, + const char *Producer, + int Optimized, const char *Flags, + unsigned RuntimeVersion) { DIBuilder *D = unwrap(Dref); DICompileUnit CU = D->createCompileUnit(Lang, File, Dir, Producer, Optimized, Flags, RuntimeVersion); return wrap(CU); } -LLVMValueRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File, - const char *Dir) { +LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File, + const char *Dir) { DIBuilder *D = unwrap(Dref); DIFile F = D->createFile(File, Dir); return wrap(F); } -LLVMValueRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, - LLVMValueRef Scope, - LLVMValueRef File, unsigned Line, - unsigned Column) { +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Line, + unsigned Column) { DIBuilder *D = unwrap(Dref); DILexicalBlock LB = D->createLexicalBlock( unwrapDI(Scope), unwrapDI(File), Line, Column); return wrap(LB); } -LLVMValueRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref, - LLVMValueRef Scope, - LLVMValueRef File, - unsigned Discriminator) { +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator) { DIBuilder *D = unwrap(Dref); DILexicalBlockFile LBF = D->createLexicalBlockFile( unwrapDI(Scope), unwrapDI(File), Discriminator); return wrap(LBF); } -LLVMValueRef LLVMDIBuilderCreateFunction( - LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, - const char *LinkageName, LLVMValueRef File, unsigned Line, - LLVMValueRef CompositeType, int IsLocalToUnit, int IsDefinition, +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name, + const char *LinkageName, LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef CompositeType, int IsLocalToUnit, int IsDefinition, unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Func) { DIBuilder *D = unwrap(Dref); DISubprogram SP = D->createFunction( @@ -91,10 +92,10 @@ LLVMValueRef LLVMDIBuilderCreateFunction( return wrap(SP); } -LLVMValueRef LLVMDIBuilderCreateLocalVariable( - LLVMDIBuilderRef Dref, unsigned Tag, LLVMValueRef Scope, const char *Name, - LLVMValueRef File, unsigned Line, LLVMValueRef Ty, int AlwaysPreserve, - unsigned Flags, unsigned ArgNo) { +LLVMMetadataRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, + int AlwaysPreserve, unsigned Flags, unsigned ArgNo) { DIBuilder *D = unwrap(Dref); DIVariable V = D->createLocalVariable( Tag, unwrapDI(Scope), Name, unwrapDI(File), Line, @@ -102,39 +103,41 @@ LLVMValueRef LLVMDIBuilderCreateLocalVariable( return wrap(V); } -LLVMValueRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, - const char *Name, uint64_t SizeInBits, - uint64_t AlignInBits, - unsigned Encoding) { +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, + const char *Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { DIBuilder *D = unwrap(Dref); DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding); return wrap(T); } -LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, - LLVMValueRef PointeeType, - uint64_t SizeInBits, - uint64_t AlignInBits, - const char *Name) { +LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, + LLVMMetadataRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name) { DIBuilder *D = unwrap(Dref); DIDerivedType T = D->createPointerType(unwrapDI(PointeeType), SizeInBits, AlignInBits, Name); return wrap(T); } -LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, - LLVMValueRef File, - LLVMValueRef ParameterTypes) { +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, LLVMMetadataRef File, + LLVMMetadataRef ParameterTypes) { DIBuilder *D = unwrap(Dref); DICompositeType CT = D->createSubroutineType( unwrapDI(File), unwrapDI(ParameterTypes)); return wrap(CT); } -LLVMValueRef LLVMDIBuilderCreateStructType( - LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, - LLVMValueRef File, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, LLVMValueRef DerivedFrom, LLVMValueRef ElementTypes) { +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, + LLVMMetadataRef ElementTypes) { DIBuilder *D = unwrap(Dref); DICompositeType CT = D->createStructType( unwrapDI(Scope), Name, unwrapDI(File), Line, @@ -143,10 +146,12 @@ LLVMValueRef LLVMDIBuilderCreateStructType( return wrap(CT); } -LLVMValueRef LLVMDIBuilderCreateMemberType( - LLVMDIBuilderRef Dref, LLVMValueRef Scope, const char *Name, - LLVMValueRef File, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, LLVMValueRef Ty) { +LLVMMetadataRef +LLVMDIBuilderCreateMemberType(LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, + unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, LLVMMetadataRef Ty) { DIBuilder *D = unwrap(Dref); DIDerivedType DT = D->createMemberType( unwrapDI(Scope), Name, unwrapDI(File), Line, @@ -154,11 +159,11 @@ LLVMValueRef LLVMDIBuilderCreateMemberType( return wrap(DT); } -LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, - uint64_t SizeInBits, - uint64_t AlignInBits, - LLVMValueRef ElementType, - LLVMValueRef Subscripts) { +LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMMetadataRef ElementType, + LLVMMetadataRef Subscripts) { DIBuilder *D = unwrap(Dref); DICompositeType CT = D->createArrayType(SizeInBits, AlignInBits, unwrapDI(ElementType), @@ -166,9 +171,10 @@ LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, return wrap(CT); } -LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMValueRef Ty, - const char *Name, LLVMValueRef File, - unsigned Line, LLVMValueRef Context) { +LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, + LLVMMetadataRef Ty, const char *Name, + LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef Context) { DIBuilder *D = unwrap(Dref); DIDerivedType DT = D->createTypedef(unwrapDI(Ty), Name, unwrapDI(File), Line, @@ -176,34 +182,35 @@ LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMValueRef Ty, return wrap(DT); } -LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, int64_t Lo, - int64_t Count) { +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, + int64_t Lo, int64_t Count) { DIBuilder *D = unwrap(Dref); DISubrange S = D->getOrCreateSubrange(Lo, Count); return wrap(S); } -LLVMValueRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, - LLVMValueRef *Data, size_t Length) { +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, + LLVMMetadataRef *Data, + size_t Length) { DIBuilder *D = unwrap(Dref); - Value **DataValue = unwrap(Data); - ArrayRef Elements(DataValue, Length); + Metadata **DataValue = unwrap(Data); + ArrayRef Elements(DataValue, Length); DIArray A = D->getOrCreateArray(Elements); return wrap(A); } -LLVMValueRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref, - LLVMValueRef *Data, - size_t Length) { +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref, + LLVMMetadataRef *Data, + size_t Length) { DIBuilder *D = unwrap(Dref); - Value **DataValue = unwrap(Data); - ArrayRef Elements(DataValue, Length); + Metadata **DataValue = unwrap(Data); + ArrayRef Elements(DataValue, Length); DITypeArray A = D->getOrCreateTypeArray(Elements); return wrap(A); } -LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, - size_t Length) { +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, + int64_t *Addr, size_t Length) { DIBuilder *D = unwrap(Dref); DIExpression Expr = D->createExpression(ArrayRef(Addr, Length)); return wrap(Expr); @@ -211,8 +218,8 @@ LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, LLVMValueRef Storage, - LLVMValueRef VarInfo, - LLVMValueRef Expr, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMBasicBlockRef Block) { DIBuilder *D = unwrap(Dref); Instruction *Instr = @@ -220,3 +227,15 @@ LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, unwrapDI(Expr), unwrap(Block)); return wrap(Instr); } + +LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef Dref, + LLVMValueRef Val, uint64_t Offset, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block) { + DIBuilder *D = unwrap(Dref); + Instruction *Instr = D->insertDbgValueIntrinsic( + unwrap(Val), Offset, unwrapDI(VarInfo), + unwrapDI(Expr), unwrap(Block)); + return wrap(Instr); +} diff --git a/bindings/go/llvm/DIBuilderBindings.h b/bindings/go/llvm/DIBuilderBindings.h index e6fe02a..e268b3c 100644 --- a/bindings/go/llvm/DIBuilderBindings.h +++ b/bindings/go/llvm/DIBuilderBindings.h @@ -14,6 +14,7 @@ #ifndef LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H #define LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H +#include "IRBindings.h" #include "llvm-c/Core.h" #ifdef __cplusplus @@ -31,93 +32,104 @@ LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef m); void LLVMDIBuilderDestroy(LLVMDIBuilderRef d); void LLVMDIBuilderFinalize(LLVMDIBuilderRef d); -LLVMValueRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef D, - unsigned Language, const char *File, - const char *Dir, - const char *Producer, int Optimized, - const char *Flags, - unsigned RuntimeVersion); - -LLVMValueRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef D, const char *File, - const char *Dir); - -LLVMValueRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef D, - LLVMValueRef Scope, - LLVMValueRef File, unsigned Line, - unsigned Column); - -LLVMValueRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef D, - LLVMValueRef Scope, - LLVMValueRef File, - unsigned Discriminator); - -LLVMValueRef LLVMDIBuilderCreateFunction( - LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, - const char *LinkageName, LLVMValueRef File, unsigned Line, - LLVMValueRef CompositeType, int IsLocalToUnit, int IsDefinition, +LLVMMetadataRef +LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef D, unsigned Language, + const char *File, const char *Dir, + const char *Producer, int Optimized, + const char *Flags, unsigned RuntimeVersion); + +LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef D, const char *File, + const char *Dir); + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef D, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Line, unsigned Column); + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef D, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator); + +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef D, LLVMMetadataRef Scope, const char *Name, + const char *LinkageName, LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef CompositeType, int IsLocalToUnit, int IsDefinition, unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Function); -LLVMValueRef LLVMDIBuilderCreateLocalVariable( - LLVMDIBuilderRef D, unsigned Tag, LLVMValueRef Scope, const char *Name, - LLVMValueRef File, unsigned Line, LLVMValueRef Ty, int AlwaysPreserve, +LLVMMetadataRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef D, unsigned Tag, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, int AlwaysPreserve, unsigned Flags, unsigned ArgNo); -LLVMValueRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef D, const char *Name, - uint64_t SizeInBits, - uint64_t AlignInBits, - unsigned Encoding); - -LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef D, - LLVMValueRef PointeeType, - uint64_t SizeInBits, - uint64_t AlignInBits, - const char *Name); - -LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef D, - LLVMValueRef File, - LLVMValueRef ParameterTypes); - -LLVMValueRef LLVMDIBuilderCreateStructType( - LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, LLVMValueRef File, - unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - LLVMValueRef DerivedFrom, LLVMValueRef ElementTypes); - -LLVMValueRef LLVMDIBuilderCreateMemberType( - LLVMDIBuilderRef D, LLVMValueRef Scope, const char *Name, LLVMValueRef File, - unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, LLVMValueRef Ty); - -LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef D, - uint64_t SizeInBits, - uint64_t AlignInBits, - LLVMValueRef ElementType, - LLVMValueRef Subscripts); - -LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef D, LLVMValueRef Ty, - const char *Name, LLVMValueRef File, - unsigned Line, LLVMValueRef Context); - -LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef D, int64_t Lo, - int64_t Count); - -LLVMValueRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef D, - LLVMValueRef *Data, size_t Length); - -LLVMValueRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef D, - LLVMValueRef *Data, - size_t Length); - -LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, - size_t Length); +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef D, + const char *Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding); + +LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef D, + LLVMMetadataRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name); + +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef D, LLVMMetadataRef File, + LLVMMetadataRef ParameterTypes); + +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef D, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, + LLVMMetadataRef ElementTypes); + +LLVMMetadataRef +LLVMDIBuilderCreateMemberType(LLVMDIBuilderRef D, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, + unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, LLVMMetadataRef Ty); + +LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef D, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMMetadataRef ElementType, + LLVMMetadataRef Subscripts); + +LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef D, + LLVMMetadataRef Ty, const char *Name, + LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef Context); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef D, int64_t Lo, + int64_t Count); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef D, + LLVMMetadataRef *Data, + size_t Length); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef D, + LLVMMetadataRef *Data, + size_t Length); + +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, + int64_t *Addr, size_t Length); LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef D, LLVMValueRef Storage, - LLVMValueRef VarInfo, - LLVMValueRef Expr, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMBasicBlockRef Block); +LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef D, LLVMValueRef Val, + uint64_t Offset, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block); + #ifdef __cplusplus -} // extern "C" +} // extern "C" #endif #endif diff --git a/bindings/go/llvm/IRBindings.cpp b/bindings/go/llvm/IRBindings.cpp index 67a54a2..fb451ef 100644 --- a/bindings/go/llvm/IRBindings.cpp +++ b/bindings/go/llvm/IRBindings.cpp @@ -12,9 +12,12 @@ //===----------------------------------------------------------------------===// #include "IRBindings.h" - #include "llvm/IR/Attributes.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" using namespace llvm; @@ -45,3 +48,54 @@ void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA) { AttributeSet::FunctionIndex, B)); Func->setAttributes(PALnew); } + +LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef C) { + return wrap(ConstantAsMetadata::get(unwrap(C))); +} + +LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen) { + return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen))); +} + +LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count) { + return wrap( + MDNode::get(*unwrap(C), ArrayRef(unwrap(MDs), Count))); +} + +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count) { + return wrap(MDTuple::getTemporary(*unwrap(C), + ArrayRef(unwrap(MDs), Count)) + .release()); +} + +void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name, + LLVMMetadataRef Val) { + NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(name); + if (!N) + return; + if (!Val) + return; + N->addOperand(unwrap(Val)); +} + +void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD) { + MDNode *N = MD ? unwrap(MD) : nullptr; + unwrap(Inst)->setMetadata(KindID, N); +} + +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New) { + auto *Node = unwrap(MD); + assert(Node->isTemporary() && "Expected temporary node"); + Node->replaceAllUsesWith(unwrap(New)); + MDNode::deleteTemporary(Node); +} + +void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line, + unsigned Col, LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt) { + unwrap(Bref)->SetCurrentDebugLocation( + DebugLoc::get(Line, Col, Scope ? unwrap(Scope) : nullptr, + InlinedAt ? unwrap(InlinedAt) : nullptr)); +} diff --git a/bindings/go/llvm/IRBindings.h b/bindings/go/llvm/IRBindings.h index cc63e4e..a53e178 100644 --- a/bindings/go/llvm/IRBindings.h +++ b/bindings/go/llvm/IRBindings.h @@ -15,12 +15,19 @@ #define LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H #include "llvm-c/Core.h" +#ifdef __cplusplus +#include "llvm/IR/Metadata.h" +#include "llvm/Support/CBindingWrapping.h" +#endif + #include #ifdef __cplusplus extern "C" { #endif +typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; + // These functions duplicate the LLVM*FunctionAttr functions in the stable C // API. We cannot use the existing functions because they take 32-bit attribute // values, and the Go bindings expose all of the LLVM attributes, some of which @@ -30,8 +37,37 @@ void LLVMAddFunctionAttr2(LLVMValueRef Fn, uint64_t PA); uint64_t LLVMGetFunctionAttr2(LLVMValueRef Fn); void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA); +LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef Val); + +LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen); +LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count); +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count); + +void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name, + LLVMMetadataRef Val); +void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD); + +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New); + +void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line, + unsigned Col, LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt); + #ifdef __cplusplus } + +namespace llvm { + +DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) + +inline Metadata **unwrap(LLVMMetadataRef *Vals) { + return reinterpret_cast(Vals); +} + +} + #endif #endif diff --git a/bindings/go/llvm/InstrumentationBindings.cpp b/bindings/go/llvm/InstrumentationBindings.cpp index b604abb..8b7bafa 100644 --- a/bindings/go/llvm/InstrumentationBindings.cpp +++ b/bindings/go/llvm/InstrumentationBindings.cpp @@ -12,10 +12,9 @@ //===----------------------------------------------------------------------===// #include "InstrumentationBindings.h" - #include "llvm-c/Core.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" #include "llvm/Transforms/Instrumentation.h" using namespace llvm; @@ -37,6 +36,11 @@ void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM) { } void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, - const char *ABIListFile) { - unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFile)); + int ABIListFilesNum, + const char **ABIListFiles) { + std::vector ABIListFilesVec; + for (int i = 0; i != ABIListFilesNum; ++i) { + ABIListFilesVec.push_back(ABIListFiles[i]); + } + unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFilesVec)); } diff --git a/bindings/go/llvm/InstrumentationBindings.h b/bindings/go/llvm/InstrumentationBindings.h index e8dbd59..97af2d5 100644 --- a/bindings/go/llvm/InstrumentationBindings.h +++ b/bindings/go/llvm/InstrumentationBindings.h @@ -28,8 +28,8 @@ void LLVMAddAddressSanitizerFunctionPass(LLVMPassManagerRef PM); void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM); void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM); void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM); -void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, - const char *ABIListFile); +void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, int ABIListFilesNum, + const char **ABIListFiles); #ifdef __cplusplus } diff --git a/bindings/go/llvm/SupportBindings.cpp b/bindings/go/llvm/SupportBindings.cpp index df5f865..5e251b7 100644 --- a/bindings/go/llvm/SupportBindings.cpp +++ b/bindings/go/llvm/SupportBindings.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "SupportBindings.h" - #include "llvm/Support/DynamicLibrary.h" #include #include diff --git a/bindings/go/llvm/dibuilder.go b/bindings/go/llvm/dibuilder.go index 1d07e98..3b1a1a6 100644 --- a/bindings/go/llvm/dibuilder.go +++ b/bindings/go/llvm/dibuilder.go @@ -121,7 +121,7 @@ type DICompileUnit struct { } // CreateCompileUnit creates compile unit debug metadata. -func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Value { +func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata { file := C.CString(cu.File) defer C.free(unsafe.Pointer(file)) dir := C.CString(cu.Dir) @@ -139,28 +139,28 @@ func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Value { flags, C.unsigned(cu.RuntimeVersion), ) - return Value{C: result} + return Metadata{C: result} } // CreateCompileUnit creates file debug metadata. -func (d *DIBuilder) CreateFile(filename, dir string) Value { +func (d *DIBuilder) CreateFile(filename, dir string) Metadata { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) cdir := C.CString(dir) defer C.free(unsafe.Pointer(cdir)) result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir) - return Value{C: result} + return Metadata{C: result} } // DILexicalBlock holds the values for creating lexical block debug metadata. type DILexicalBlock struct { - File Value + File Metadata Line int Column int } // CreateCompileUnit creates lexical block debug metadata. -func (d *DIBuilder) CreateLexicalBlock(diScope Value, b DILexicalBlock) Value { +func (d *DIBuilder) CreateLexicalBlock(diScope Metadata, b DILexicalBlock) Metadata { result := C.LLVMDIBuilderCreateLexicalBlock( d.ref, diScope.C, @@ -168,22 +168,22 @@ func (d *DIBuilder) CreateLexicalBlock(diScope Value, b DILexicalBlock) Value { C.unsigned(b.Line), C.unsigned(b.Column), ) - return Value{C: result} + return Metadata{C: result} } -func (d *DIBuilder) CreateLexicalBlockFile(diScope Value, diFile Value, discriminator int) Value { +func (d *DIBuilder) CreateLexicalBlockFile(diScope Metadata, diFile Metadata, discriminator int) Metadata { result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C, C.unsigned(discriminator)) - return Value{C: result} + return Metadata{C: result} } // DIFunction holds the values for creating function debug metadata. type DIFunction struct { Name string LinkageName string - File Value + File Metadata Line int - Type Value + Type Metadata LocalToUnit bool IsDefinition bool ScopeLine int @@ -193,7 +193,7 @@ type DIFunction struct { } // CreateCompileUnit creates function debug metadata. -func (d *DIBuilder) CreateFunction(diScope Value, f DIFunction) Value { +func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata { name := C.CString(f.Name) defer C.free(unsafe.Pointer(name)) linkageName := C.CString(f.LinkageName) @@ -213,16 +213,16 @@ func (d *DIBuilder) CreateFunction(diScope Value, f DIFunction) Value { boolToCInt(f.Optimized), f.Function.C, ) - return Value{C: result} + return Metadata{C: result} } // DILocalVariable holds the values for creating local variable debug metadata. type DILocalVariable struct { Tag dwarf.Tag Name string - File Value + File Metadata Line int - Type Value + Type Metadata AlwaysPreserve bool Flags int @@ -232,7 +232,7 @@ type DILocalVariable struct { } // CreateLocalVariable creates local variable debug metadata. -func (d *DIBuilder) CreateLocalVariable(scope Value, v DILocalVariable) Value { +func (d *DIBuilder) CreateLocalVariable(scope Metadata, v DILocalVariable) Metadata { name := C.CString(v.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateLocalVariable( @@ -247,7 +247,7 @@ func (d *DIBuilder) CreateLocalVariable(scope Value, v DILocalVariable) Value { C.unsigned(v.Flags), C.unsigned(v.ArgNo), ) - return Value{C: result} + return Metadata{C: result} } // DIBasicType holds the values for creating basic type debug metadata. @@ -259,7 +259,7 @@ type DIBasicType struct { } // CreateBasicType creates basic type debug metadata. -func (d *DIBuilder) CreateBasicType(t DIBasicType) Value { +func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateBasicType( @@ -269,19 +269,19 @@ func (d *DIBuilder) CreateBasicType(t DIBasicType) Value { C.uint64_t(t.AlignInBits), C.unsigned(t.Encoding), ) - return Value{C: result} + return Metadata{C: result} } // DIPointerType holds the values for creating pointer type debug metadata. type DIPointerType struct { - Pointee Value + Pointee Metadata SizeInBits uint64 AlignInBits uint64 // optional Name string // optional } // CreateBasicType creates basic type debug metadata. -func (d *DIBuilder) CreatePointerType(t DIPointerType) Value { +func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreatePointerType( @@ -291,40 +291,40 @@ func (d *DIBuilder) CreatePointerType(t DIPointerType) Value { C.uint64_t(t.AlignInBits), name, ) - return Value{C: result} + return Metadata{C: result} } // DISubroutineType holds the values for creating subroutine type debug metadata. type DISubroutineType struct { // File is the file in which the subroutine type is defined. - File Value + File Metadata // Parameters contains the subroutine parameter types, // including the return type at the 0th index. - Parameters []Value + Parameters []Metadata } // CreateSubroutineType creates subroutine type debug metadata. -func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Value { +func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata { params := d.getOrCreateTypeArray(t.Parameters) result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C) - return Value{C: result} + return Metadata{C: result} } // DIStructType holds the values for creating struct type debug metadata. type DIStructType struct { Name string - File Value + File Metadata Line int SizeInBits uint64 AlignInBits uint64 Flags int - DerivedFrom Value - Elements []Value + DerivedFrom Metadata + Elements []Metadata } // CreateStructType creates struct type debug metadata. -func (d *DIBuilder) CreateStructType(scope Value, t DIStructType) Value { +func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata { elements := d.getOrCreateArray(t.Elements) name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) @@ -340,23 +340,23 @@ func (d *DIBuilder) CreateStructType(scope Value, t DIStructType) Value { t.DerivedFrom.C, elements.C, ) - return Value{C: result} + return Metadata{C: result} } // DIMemberType holds the values for creating member type debug metadata. type DIMemberType struct { Name string - File Value + File Metadata Line int SizeInBits uint64 AlignInBits uint64 OffsetInBits uint64 Flags int - Type Value + Type Metadata } // CreateMemberType creates struct type debug metadata. -func (d *DIBuilder) CreateMemberType(scope Value, t DIMemberType) Value { +func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateMemberType( @@ -371,7 +371,7 @@ func (d *DIBuilder) CreateMemberType(scope Value, t DIMemberType) Value { C.unsigned(t.Flags), t.Type.C, ) - return Value{C: result} + return Metadata{C: result} } // DISubrange describes an integer value range. @@ -384,13 +384,13 @@ type DISubrange struct { type DIArrayType struct { SizeInBits uint64 AlignInBits uint64 - ElementType Value + ElementType Metadata Subscripts []DISubrange } // CreateArrayType creates struct type debug metadata. -func (d *DIBuilder) CreateArrayType(t DIArrayType) Value { - subscriptsSlice := make([]Value, len(t.Subscripts)) +func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata { + subscriptsSlice := make([]Metadata, len(t.Subscripts)) for i, s := range t.Subscripts { subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count) } @@ -402,20 +402,20 @@ func (d *DIBuilder) CreateArrayType(t DIArrayType) Value { t.ElementType.C, subscripts.C, ) - return Value{C: result} + return Metadata{C: result} } // DITypedef holds the values for creating typedef type debug metadata. type DITypedef struct { - Type Value + Type Metadata Name string - File Value + File Metadata Line int - Context Value + Context Metadata } // CreateTypedef creates typedef type debug metadata. -func (d *DIBuilder) CreateTypedef(t DITypedef) Value { +func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateTypedef( @@ -426,64 +426,63 @@ func (d *DIBuilder) CreateTypedef(t DITypedef) Value { C.unsigned(t.Line), t.Context.C, ) - return Value{C: result} + return Metadata{C: result} } // getOrCreateSubrange gets a metadata node for the specified subrange, // creating if required. -func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Value { +func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata { result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count)) - return Value{C: result} + return Metadata{C: result} } // getOrCreateArray gets a metadata node containing the specified values, // creating if required. -func (d *DIBuilder) getOrCreateArray(values []Value) Value { +func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata { if len(values) == 0 { - return Value{} - } - var data *C.LLVMValueRef - length := len(values) - if length > 0 { - data = &values[0].C + return Metadata{} } + data, length := llvmMetadataRefs(values) result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length)) - return Value{C: result} + return Metadata{C: result} } // getOrCreateTypeArray gets a metadata node for a type array containing the // specified values, creating if required. -func (d *DIBuilder) getOrCreateTypeArray(values []Value) Value { +func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata { if len(values) == 0 { - return Value{} - } - var data *C.LLVMValueRef - length := len(values) - if length > 0 { - data = &values[0].C + return Metadata{} } + data, length := llvmMetadataRefs(values) result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length)) - return Value{C: result} + return Metadata{C: result} } // CreateExpression creates a new descriptor for the specified // variable which has a complex address expression for its address. -func (d *DIBuilder) CreateExpression(addr []int64) Value { +func (d *DIBuilder) CreateExpression(addr []int64) Metadata { var data *C.int64_t if len(addr) > 0 { data = (*C.int64_t)(unsafe.Pointer(&addr[0])) } result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr))) - return Value{C: result} + return Metadata{C: result} } // InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the // specified basic block for the given value and associated debug metadata. -func (d *DIBuilder) InsertDeclareAtEnd(v, diVarInfo, expr Value, bb BasicBlock) Value { +func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value { result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C) return Value{C: result} } +// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the +// specified basic block for the given value and associated debug metadata. +func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value { + result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C) + return Value{C: result} +} + func boolToCInt(v bool) C.int { if v { return 1 diff --git a/bindings/go/llvm/executionengine.go b/bindings/go/llvm/executionengine.go index 26b7524..94d4e83 100644 --- a/bindings/go/llvm/executionengine.go +++ b/bindings/go/llvm/executionengine.go @@ -30,11 +30,25 @@ type GenericValue struct { type ExecutionEngine struct { C C.LLVMExecutionEngineRef } + type MCJITCompilerOptions struct { - OptLevel uint - CodeModel CodeModel - NoFramePointerElim bool - EnableFastISel bool + C C.struct_LLVMMCJITCompilerOptions +} + +func (options *MCJITCompilerOptions) SetMCJITOptimizationLevel(level uint) { + options.C.OptLevel = C.uint(level) +} + +func (options *MCJITCompilerOptions) SetMCJITNoFramePointerElim(nfp bool) { + options.C.NoFramePointerElim = boolToLLVMBool(nfp) +} + +func (options *MCJITCompilerOptions) SetMCJITEnableFastISel(fastisel bool) { + options.C.EnableFastISel = boolToLLVMBool(fastisel) +} + +func (options *MCJITCompilerOptions) SetMCJITCodeModel(CodeModel CodeModel) { + options.C.CodeModel = C.LLVMCodeModel(CodeModel) } // helpers @@ -96,15 +110,15 @@ func NewInterpreter(m Module) (ee ExecutionEngine, err error) { return } +func NewMCJITCompilerOptions() MCJITCompilerOptions { + var options C.struct_LLVMMCJITCompilerOptions + C.LLVMInitializeMCJITCompilerOptions(&options, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{}))) + return MCJITCompilerOptions{options} +} + func NewMCJITCompiler(m Module, options MCJITCompilerOptions) (ee ExecutionEngine, err error) { var cmsg *C.char - copts := C.struct_LLVMMCJITCompilerOptions{ - OptLevel: C.unsigned(options.OptLevel), - CodeModel: C.LLVMCodeModel(options.CodeModel), - NoFramePointerElim: boolToLLVMBool(options.NoFramePointerElim), - EnableFastISel: boolToLLVMBool(options.EnableFastISel), - } - fail := C.LLVMCreateMCJITCompilerForModule(&ee.C, m.C, &copts, C.size_t(unsafe.Sizeof(copts)), &cmsg) + fail := C.LLVMCreateMCJITCompilerForModule(&ee.C, m.C, &options.C, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{})), &cmsg) if fail != 0 { ee.C = nil err = errors.New(C.GoString(cmsg)) diff --git a/bindings/go/llvm/executionengine_test.go b/bindings/go/llvm/executionengine_test.go index 1a3fd45..2b6a3ca 100644 --- a/bindings/go/llvm/executionengine_test.go +++ b/bindings/go/llvm/executionengine_test.go @@ -66,7 +66,12 @@ func TestFactorial(t *testing.T) { return } - engine, err := NewMCJITCompiler(mod, MCJITCompilerOptions{OptLevel: 2}) + options := NewMCJITCompilerOptions() + options.SetMCJITOptimizationLevel(2) + options.SetMCJITEnableFastISel(true) + options.SetMCJITNoFramePointerElim(true) + options.SetMCJITCodeModel(CodeModelJITDefault) + engine, err := NewMCJITCompiler(mod, options) if err != nil { t.Errorf("Error creating JIT: %s", err) return diff --git a/bindings/go/llvm/ir.go b/bindings/go/llvm/ir.go index 7834f5c..e5916a1 100644 --- a/bindings/go/llvm/ir.go +++ b/bindings/go/llvm/ir.go @@ -55,6 +55,9 @@ type ( Use struct { C C.LLVMUseRef } + Metadata struct { + C C.LLVMMetadataRef + } Attribute uint64 Opcode C.LLVMOpcode TypeKind C.LLVMTypeKind @@ -80,6 +83,9 @@ func (c Use) IsNil() bool { return c.C == nil } // helpers func llvmTypeRefPtr(t *Type) *C.LLVMTypeRef { return (*C.LLVMTypeRef)(unsafe.Pointer(t)) } func llvmValueRefPtr(t *Value) *C.LLVMValueRef { return (*C.LLVMValueRef)(unsafe.Pointer(t)) } +func llvmMetadataRefPtr(t *Metadata) *C.LLVMMetadataRef { + return (*C.LLVMMetadataRef)(unsafe.Pointer(t)) +} func llvmBasicBlockRefPtr(t *BasicBlock) *C.LLVMBasicBlockRef { return (*C.LLVMBasicBlockRef)(unsafe.Pointer(t)) } @@ -99,6 +105,15 @@ func llvmValueRefs(values []Value) (*C.LLVMValueRef, C.unsigned) { return pt, ptlen } +func llvmMetadataRefs(mds []Metadata) (*C.LLVMMetadataRef, C.unsigned) { + var pt *C.LLVMMetadataRef + ptlen := C.unsigned(len(mds)) + if ptlen > 0 { + pt = llvmMetadataRefPtr(&mds[0]) + } + return pt, ptlen +} + //------------------------------------------------------------------------- // llvm.Attribute //------------------------------------------------------------------------- @@ -421,10 +436,10 @@ func (m Module) SetInlineAsm(asm string) { C.LLVMSetModuleInlineAsm(m.C, casm) } -func (m Module) AddNamedMetadataOperand(name string, operand Value) { +func (m Module) AddNamedMetadataOperand(name string, operand Metadata) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - C.LLVMAddNamedMetadataOperand(m.C, cname, operand.C) + C.LLVMAddNamedMetadataOperand2(m.C, cname, operand.C) } func (m Module) Context() (c Context) { @@ -628,8 +643,8 @@ func (v Value) Metadata(kind int) (rv Value) { rv.C = C.LLVMGetMetadata(v.C, C.unsigned(kind)) return } -func (v Value) SetMetadata(kind int, node Value) { - C.LLVMSetMetadata(v.C, C.unsigned(kind), node.C) +func (v Value) SetMetadata(kind int, node Metadata) { + C.LLVMSetMetadata2(v.C, C.unsigned(kind), node.C) } // Conversion functions. @@ -723,26 +738,24 @@ func (v Value) IsUndef() bool { return C.LLVMIsUndef(v.C) != 0 } func ConstPointerNull(t Type) (v Value) { v.C = C.LLVMConstPointerNull(t.C); return } // Operations on metadata -func (c Context) MDString(str string) (v Value) { +func (c Context) MDString(str string) (md Metadata) { cstr := C.CString(str) defer C.free(unsafe.Pointer(cstr)) - v.C = C.LLVMMDStringInContext(c.C, cstr, C.unsigned(len(str))) + md.C = C.LLVMMDString2(c.C, cstr, C.unsigned(len(str))) return } -func MDString(str string) (v Value) { - cstr := C.CString(str) - defer C.free(unsafe.Pointer(cstr)) - v.C = C.LLVMMDString(cstr, C.unsigned(len(str))) +func (c Context) MDNode(mds []Metadata) (md Metadata) { + ptr, nvals := llvmMetadataRefs(mds) + md.C = C.LLVMMDNode2(c.C, ptr, nvals) return } -func (c Context) MDNode(vals []Value) (v Value) { - ptr, nvals := llvmValueRefs(vals) - v.C = C.LLVMMDNodeInContext(c.C, ptr, nvals) +func (c Context) TemporaryMDNode(mds []Metadata) (md Metadata) { + ptr, nvals := llvmMetadataRefs(mds) + md.C = C.LLVMTemporaryMDNode(c.C, ptr, nvals) return } -func MDNode(vals []Value) (v Value) { - ptr, nvals := llvmValueRefs(vals) - v.C = C.LLVMMDNode(ptr, nvals) +func (v Value) ConstantAsMetadata() (md Metadata) { + md.C = C.LLVMConstantAsMetadata(v.C) return } @@ -1188,8 +1201,9 @@ func (b Builder) InsertWithName(instr Value, name string) { func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) } // Metadata -func (b Builder) SetCurrentDebugLocation(v Value) { C.LLVMSetCurrentDebugLocation(b.C, v.C) } -func (b Builder) CurrentDebugLocation() (v Value) { v.C = C.LLVMGetCurrentDebugLocation(b.C); return } +func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metadata) { + C.LLVMSetCurrentDebugLocation2(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C) +} func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value { f := module.NamedFunction("llvm.dbg.declare") @@ -1822,3 +1836,11 @@ func (pm PassManager) FinalizeFunc() bool { return C.LLVMFinalizeFunctionPassMan // the module provider. // See llvm::PassManagerBase::~PassManagerBase. func (pm PassManager) Dispose() { C.LLVMDisposePassManager(pm.C) } + +//------------------------------------------------------------------------- +// llvm.Metadata +//------------------------------------------------------------------------- + +func (md Metadata) ReplaceAllUsesWith(new Metadata) { + C.LLVMMetadataReplaceAllUsesWith(md.C, new.C) +} diff --git a/bindings/go/llvm/linker.go b/bindings/go/llvm/linker.go index 31e9ad2..64d794e 100644 --- a/bindings/go/llvm/linker.go +++ b/bindings/go/llvm/linker.go @@ -20,16 +20,9 @@ package llvm import "C" import "errors" -type LinkerMode C.LLVMLinkerMode - -const ( - LinkerDestroySource = C.LLVMLinkerDestroySource - LinkerPreserveSource = C.LLVMLinkerPreserveSource -) - -func LinkModules(Dest, Src Module, Mode LinkerMode) error { +func LinkModules(Dest, Src Module) error { var cmsg *C.char - failed := C.LLVMLinkModules(Dest.C, Src.C, C.LLVMLinkerMode(Mode), &cmsg) + failed := C.LLVMLinkModules(Dest.C, Src.C, 0, &cmsg) if failed != 0 { err := errors.New(C.GoString(cmsg)) C.LLVMDisposeMessage(cmsg) diff --git a/bindings/go/llvm/transforms_instrumentation.go b/bindings/go/llvm/transforms_instrumentation.go index 9b191b2..73e2732 100644 --- a/bindings/go/llvm/transforms_instrumentation.go +++ b/bindings/go/llvm/transforms_instrumentation.go @@ -36,8 +36,11 @@ func (pm PassManager) AddMemorySanitizerPass() { C.LLVMAddMemorySanitizerPass(pm.C) } -func (pm PassManager) AddDataFlowSanitizerPass(abilist string) { - cabilist := C.CString(abilist) - defer C.free(unsafe.Pointer(cabilist)) - C.LLVMAddDataFlowSanitizerPass(pm.C, cabilist) +func (pm PassManager) AddDataFlowSanitizerPass(abilist []string) { + abiliststrs := make([]*C.char, len(abilist)) + for i, arg := range abilist { + abiliststrs[i] = C.CString(arg) + defer C.free(unsafe.Pointer(abiliststrs[i])) + } + C.LLVMAddDataFlowSanitizerPass(pm.C, C.int(len(abilist)), &abiliststrs[0]) } diff --git a/bindings/ocaml/CMakeLists.txt b/bindings/ocaml/CMakeLists.txt new file mode 100644 index 0000000..2058368 --- /dev/null +++ b/bindings/ocaml/CMakeLists.txt @@ -0,0 +1,11 @@ +add_subdirectory(llvm) +add_subdirectory(all_backends) +add_subdirectory(analysis) +add_subdirectory(backends) +add_subdirectory(bitreader) +add_subdirectory(bitwriter) +add_subdirectory(irreader) +add_subdirectory(linker) +add_subdirectory(target) +add_subdirectory(transforms) +add_subdirectory(executionengine) diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index 5e00cf5..1f65a7b 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -32,6 +32,12 @@ endif include $(LEVEL)/Makefile.common +# Used in out-of-tree builds of OCaml bindings only. +ifdef SYSTEM_LLVM_CONFIG +LLVM_CONFIG = $(SYSTEM_LLVM_CONFIG) +LLVMLibsOptions += $(shell $(LLVM_CONFIG) --ldflags) +endif + # Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the # user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) @@ -65,6 +71,10 @@ OCAMLRPATH := $(RPATH) -Wl,'$$ORIGIN/../../lib' endif endif +# See http://caml.inria.fr/mantis/view.php?id=6642 +OCAMLORIGIN := -ccopt -L'$$CAMLORIGIN/..' \ + -ccopt $(RPATH) -ccopt -Wl,'$$CAMLORIGIN/..' + # Tools OCAMLCFLAGS += -I $(OcamlDir) $(addprefix -package ,$(FindlibPackages)) @@ -92,16 +102,18 @@ Compile.CMX := $(strip $(OCAMLFIND) opt -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) ifdef OCAMLSTUBS # -dllib is engaged with ocamlc builds, $(OCAMLSTUBFLAGS) in ocamlc -custom builds. Archive.CMA := $(strip $(OCAMLFIND) c -a -dllib -l$(LIBRARYNAME) $(OCAMLSTUBFLAGS) \ - $(OCAMLDEBUGFLAG) -o) + $(OCAMLDEBUGFLAG) $(OCAMLORIGIN) -o) else Archive.CMA := $(strip $(OCAMLFIND) c -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ - -o) + $(OCAMLORIGIN) -o) endif ifdef OCAMLSTUBS -Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLSTUBFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLSTUBFLAGS) $(OCAMLDEBUGFLAG) \ + $(OCAMLORIGIN) -o) else -Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + $(OCAMLORIGIN) -o) endif # Source files @@ -237,8 +249,8 @@ uninstall-local:: uninstall-shared $(SharedLib): $(ObjectsO) $(OcamlDir)/.dir $(Echo) "Building $(BuildMode) $(notdir $@)" - $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) $(LLVMLibsOptions) \ - -o $@ $(ObjectsO) + $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) -o $@ $(ObjectsO) \ + $(LLVMLibsOptions) clean-shared:: -$(Verb) $(RM) -f $(SharedLib) @@ -255,8 +267,9 @@ uninstall-shared:: endif -##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## +##===- Deposit dependent libraries adjacent to OCaml libs -----------------===## +ifndef SYSTEM_LLVM_CONFIG all-local:: build-deplibs clean-local:: clean-deplibs install-local:: install-deplibs @@ -281,7 +294,7 @@ install-deplibs: uninstall-deplibs: $(Verb) $(RM) -f $(DestLibs) - +endif ##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## diff --git a/bindings/ocaml/all_backends/CMakeLists.txt b/bindings/ocaml/all_backends/CMakeLists.txt new file mode 100644 index 0000000..716a49c --- /dev/null +++ b/bindings/ocaml/all_backends/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_all_backends + OCAML llvm_all_backends + OCAMLDEP llvm + C all_backends_ocaml + LLVM ${LLVM_TARGETS_TO_BUILD}) diff --git a/bindings/ocaml/analysis/CMakeLists.txt b/bindings/ocaml/analysis/CMakeLists.txt new file mode 100644 index 0000000..f8ca84d --- /dev/null +++ b/bindings/ocaml/analysis/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_analysis + OCAML llvm_analysis + OCAMLDEP llvm + C analysis_ocaml + LLVM analysis) diff --git a/bindings/ocaml/backends/CMakeLists.txt b/bindings/ocaml/backends/CMakeLists.txt new file mode 100644 index 0000000..a980638 --- /dev/null +++ b/bindings/ocaml/backends/CMakeLists.txt @@ -0,0 +1,27 @@ +foreach(TARGET ${LLVM_TARGETS_TO_BUILD}) + set(OCAML_LLVM_TARGET ${TARGET}) + + foreach( ext ml mli ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/llvm_backend.${ext}.in" + "${CMAKE_CURRENT_BINARY_DIR}/llvm_${TARGET}.${ext}") + endforeach() + + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/backend_ocaml.c" + "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_ocaml.c") + + add_ocaml_library(llvm_${TARGET} + OCAML llvm_${TARGET} + C ${TARGET}_ocaml + CFLAGS -DTARGET=${TARGET} + LLVM ${TARGET} + NOCOPY) + + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/META.llvm_backend.in" + "${LLVM_LIBRARY_DIR}/ocaml/META.llvm_${TARGET}") + + install(FILES "${LLVM_LIBRARY_DIR}/ocaml/META.llvm_${TARGET}" + DESTINATION lib/ocaml) +endforeach() diff --git a/bindings/ocaml/bitreader/CMakeLists.txt b/bindings/ocaml/bitreader/CMakeLists.txt new file mode 100644 index 0000000..8d16103 --- /dev/null +++ b/bindings/ocaml/bitreader/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_bitreader + OCAML llvm_bitreader + OCAMLDEP llvm + C bitreader_ocaml + LLVM bitreader) diff --git a/bindings/ocaml/bitwriter/CMakeLists.txt b/bindings/ocaml/bitwriter/CMakeLists.txt new file mode 100644 index 0000000..5a14498 --- /dev/null +++ b/bindings/ocaml/bitwriter/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_bitwriter + OCAML llvm_bitwriter + OCAMLDEP llvm + C bitwriter_ocaml + LLVM bitwriter) diff --git a/bindings/ocaml/executionengine/CMakeLists.txt b/bindings/ocaml/executionengine/CMakeLists.txt new file mode 100644 index 0000000..ae9af08 --- /dev/null +++ b/bindings/ocaml/executionengine/CMakeLists.txt @@ -0,0 +1,6 @@ +add_ocaml_library(llvm_executionengine + OCAML llvm_executionengine + OCAMLDEP llvm llvm_target + C executionengine_ocaml + LLVM executionengine mcjit native + PKG ctypes) diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c index 0557efc..b799250 100644 --- a/bindings/ocaml/executionengine/executionengine_ocaml.c +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -115,8 +115,12 @@ CAMLprim value llvm_ee_add_global_mapping(LLVMValueRef Global, value Ptr, return Val_unit; } -/* Llvm.llvalue -> llexecutionengine -> int64 */ -CAMLprim value llvm_ee_get_pointer_to_global(LLVMValueRef Global, - LLVMExecutionEngineRef EE) { - return caml_copy_int64((int64_t) LLVMGetPointerToGlobal(EE, Global)); +CAMLprim value llvm_ee_get_global_value_address(value Name, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetGlobalValueAddress(EE, String_val(Name))); +} + +CAMLprim value llvm_ee_get_function_address(value Name, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetFunctionAddress(EE, String_val(Name))); } diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index c0ff330..34031be 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -45,15 +45,27 @@ external data_layout : llexecutionengine -> Llvm_target.DataLayout.t = "llvm_ee_get_data_layout" external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit = "llvm_ee_add_global_mapping" -external get_pointer_to_global_ : Llvm.llvalue -> llexecutionengine -> int64 - = "llvm_ee_get_pointer_to_global" +external get_global_value_address_ : string -> llexecutionengine -> int64 + = "llvm_ee_get_global_value_address" +external get_function_address_ : string -> llexecutionengine -> int64 + = "llvm_ee_get_function_address" let add_global_mapping llval ptr ee = add_global_mapping_ llval (Ctypes.raw_address_of_ptr (Ctypes.to_voidp ptr)) ee -let get_pointer_to_global llval typ ee = - Ctypes.coerce (let open Ctypes in ptr void) typ - (Ctypes.ptr_of_raw_address (get_pointer_to_global_ llval ee)) +let get_global_value_address name typ ee = + let vptr = get_global_value_address_ name ee in + if Int64.to_int vptr <> 0 then + let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr)) + else + raise (Error ("Value " ^ name ^ " not found")) + +let get_function_address name typ ee = + let fptr = get_function_address_ name ee in + if Int64.to_int fptr <> 0 then + let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr) + else + raise (Error ("Function " ^ name ^ " not found")) (* The following are not bound. Patches are welcome. target_machine : llexecutionengine -> Llvm_target.TargetMachine.t diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli index b07151d..bc076be 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.mli +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -76,9 +76,18 @@ val data_layout : llexecutionengine -> Llvm_target.DataLayout.t All uses of [gv] in the compiled code will refer to [ptr]. *) val add_global_mapping : Llvm.llvalue -> 'a Ctypes.ptr -> llexecutionengine -> unit -(** [get_pointer_to_global gv typ ee] returns the value of the global - variable [gv] in the execution engine [ee] as type [typ], which may - be a pointer type (e.g. [int ptr typ]) for global variables or - a function (e.g. [(int -> int) typ]) type for functions, and which - will be live as long as [gv] and [ee] are. *) -val get_pointer_to_global : Llvm.llvalue -> 'a Ctypes.typ -> llexecutionengine -> 'a +(** [get_global_value_address id typ ee] returns a pointer to the + identifier [id] as type [typ], which will be a pointer type for a + value, and which will be live as long as [id] and [ee] + are. Caution: this function finalizes, i.e. forces code + generation, all loaded modules. Further modifications to the + modules will not have any effect. *) +val get_global_value_address : string -> 'a Ctypes.typ -> llexecutionengine -> 'a + +(** [get_function_address fn typ ee] returns a pointer to the function + [fn] as type [typ], which will be a pointer type for a function + (e.g. [(int -> int) typ]), and which will be live as long as [fn] + and [ee] are. Caution: this function finalizes, i.e. forces code + generation, all loaded modules. Further modifications to the + modules will not have any effect. *) +val get_function_address : string -> 'a Ctypes.typ -> llexecutionengine -> 'a diff --git a/bindings/ocaml/irreader/CMakeLists.txt b/bindings/ocaml/irreader/CMakeLists.txt new file mode 100644 index 0000000..87d269b --- /dev/null +++ b/bindings/ocaml/irreader/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_irreader + OCAML llvm_irreader + OCAMLDEP llvm + C irreader_ocaml + LLVM irreader) diff --git a/bindings/ocaml/linker/CMakeLists.txt b/bindings/ocaml/linker/CMakeLists.txt new file mode 100644 index 0000000..b6bc8ac --- /dev/null +++ b/bindings/ocaml/linker/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_linker + OCAML llvm_linker + OCAMLDEP llvm + C linker_ocaml + LLVM linker) diff --git a/bindings/ocaml/linker/linker_ocaml.c b/bindings/ocaml/linker/linker_ocaml.c index ed37777..3b8512a 100644 --- a/bindings/ocaml/linker/linker_ocaml.c +++ b/bindings/ocaml/linker/linker_ocaml.c @@ -23,11 +23,11 @@ void llvm_raise(value Prototype, char *Message); -/* llmodule -> llmodule -> Mode.t -> unit */ -CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) { +/* llmodule -> llmodule -> unit */ +CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src) { char* Message; - if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message)) + if (LLVMLinkModules(Dst, Src, 0, &Message)) llvm_raise(*caml_named_value("Llvm_linker.Error"), Message); return Val_unit; diff --git a/bindings/ocaml/linker/llvm_linker.ml b/bindings/ocaml/linker/llvm_linker.ml index 5854d70..3044abd 100644 --- a/bindings/ocaml/linker/llvm_linker.ml +++ b/bindings/ocaml/linker/llvm_linker.ml @@ -11,11 +11,5 @@ exception Error of string let () = Callback.register_exception "Llvm_linker.Error" (Error "") -module Mode = struct - type t = - | DestroySource - | PreserveSource -end - -external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit +external link_modules : Llvm.llmodule -> Llvm.llmodule -> unit = "llvm_link_modules" diff --git a/bindings/ocaml/linker/llvm_linker.mli b/bindings/ocaml/linker/llvm_linker.mli index 4def7a8..06c3b92 100644 --- a/bindings/ocaml/linker/llvm_linker.mli +++ b/bindings/ocaml/linker/llvm_linker.mli @@ -14,13 +14,6 @@ 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 +val link_modules : Llvm.llmodule -> Llvm.llmodule -> unit \ No newline at end of file diff --git a/bindings/ocaml/llvm/CMakeLists.txt b/bindings/ocaml/llvm/CMakeLists.txt new file mode 100644 index 0000000..4956fa4 --- /dev/null +++ b/bindings/ocaml/llvm/CMakeLists.txt @@ -0,0 +1,11 @@ +add_ocaml_library(llvm + OCAML llvm + C llvm_ocaml + LLVM core support) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/META.llvm.in" + "${LLVM_LIBRARY_DIR}/ocaml/META.llvm") + +install(FILES "${LLVM_LIBRARY_DIR}/ocaml/META.llvm" + DESTINATION lib/ocaml) diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in index f9808c7..92896e3 100644 --- a/bindings/ocaml/llvm/META.llvm.in +++ b/bindings/ocaml/llvm/META.llvm.in @@ -61,6 +61,14 @@ package "scalar_opts" ( archive(native) = "llvm_scalar_opts.cmxa" ) +package "transform_utils" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Transform utilities for LLVM" + archive(byte) = "llvm_transform_utils.cma" + archive(native) = "llvm_transform_utils.cmxa" +) + package "vectorize" ( requires = "llvm" version = "@PACKAGE_VERSION@" diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile index fb682c7..c0785a1 100644 --- a/bindings/ocaml/llvm/Makefile +++ b/bindings/ocaml/llvm/Makefile @@ -13,7 +13,7 @@ LEVEL := ../../.. LIBRARYNAME := llvm -UsedComponents := core transformutils +UsedComponents := core UsedOcamlLibs := llvm ExtraLibs := -lstdc++ diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 0df4d40..9a3cb1f 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -313,7 +313,6 @@ external mdkind_id : llcontext -> string -> llmdkind = "llvm_mdkind_id" (*===-- Modules -----------------------------------------------------------===*) external create_module : llcontext -> string -> llmodule = "llvm_create_module" external dispose_module : llmodule -> unit = "llvm_dispose_module" -external clone_module : llmodule -> llmodule = "LLVMCloneModule" external target_triple: llmodule -> string = "llvm_target_triple" external set_target_triple: string -> llmodule -> unit @@ -460,6 +459,7 @@ external clear_metadata : llvalue -> llmdkind -> unit = "llvm_clear_metadata" (*--... Operations on metadata .......,.....................................--*) external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" +external mdnull : llcontext -> llvalue = "llvm_mdnull" external get_mdstring : llvalue -> string option = "llvm_get_mdstring" external get_named_metadata : llmodule -> string -> llvalue array = "llvm_get_namedmd" @@ -1300,6 +1300,8 @@ external build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> (*--... Miscellaneous instructions .........................................--*) external build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> llvalue = "llvm_build_phi" +external build_empty_phi : lltype -> string -> llbuilder -> llvalue + = "llvm_build_empty_phi" external build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue = "llvm_build_call" external build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index e5e90c3..dcda027 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -431,9 +431,6 @@ val create_module : llcontext -> string -> llmodule [llvm::Module::~Module]. *) val dispose_module : llmodule -> unit -(** [clone_module m] returns an exact copy of module [m]. *) -val clone_module : llmodule -> llmodule - (** [target_triple m] is the target specifier for the module [m], something like [i686-apple-darwin8]. See the method [llvm::Module::getTargetTriple]. *) val target_triple: llmodule -> string @@ -822,6 +819,9 @@ val mdstring : llcontext -> string -> llvalue See the method [llvm::MDNode::get]. *) val mdnode : llcontext -> llvalue array -> llvalue +(** [mdnull c ] returns a null MDNode in context [c]. *) +val mdnull : llcontext -> llvalue + (** [get_mdstring v] returns the MDString. See the method [llvm::MDString::getString] *) val get_mdstring : llvalue -> string option @@ -2422,6 +2422,12 @@ val build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> val build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> llvalue +(** [build_empty_phi ty name b] creates a + [%name = phi %ty] instruction at the position specified by + the instruction builder [b]. [ty] is the type of the instruction. + See the method [llvm::LLVMBuilder::CreatePHI]. *) +val build_empty_phi : lltype -> string -> llbuilder -> llvalue + (** [build_call fn args name b] creates a [%name = call %fn(args...)] instruction at the position specified by the instruction builder [b]. diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 63c235d..3889f92 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -666,6 +666,11 @@ CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) { Wosize_val(ElementVals)); } +/* llcontext -> llvalue */ +CAMLprim LLVMValueRef llvm_mdnull(LLVMContextRef C) { + return NULL; +} + /* llvalue -> string option */ CAMLprim value llvm_get_mdstring(LLVMValueRef V) { CAMLparam0(); @@ -2186,6 +2191,15 @@ CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { return PhiNode; } +/* lltype -> string -> llbuilder -> value */ +CAMLprim LLVMValueRef llvm_build_empty_phi(LLVMTypeRef Type, value Name, value B) { + LLVMValueRef PhiNode; + + return LLVMBuildPhi(Builder_val(B), Type, String_val(Name)); + + return PhiNode; +} + /* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_call(LLVMValueRef Fn, value Params, value Name, value B) { diff --git a/bindings/ocaml/target/CMakeLists.txt b/bindings/ocaml/target/CMakeLists.txt new file mode 100644 index 0000000..adee0fc --- /dev/null +++ b/bindings/ocaml/target/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_target + OCAML llvm_target + OCAMLDEP llvm + C target_ocaml + LLVM target) diff --git a/bindings/ocaml/transforms/CMakeLists.txt b/bindings/ocaml/transforms/CMakeLists.txt new file mode 100644 index 0000000..beb8694 --- /dev/null +++ b/bindings/ocaml/transforms/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(ipo) +add_subdirectory(passmgr_builder) +add_subdirectory(scalar_opts) +add_subdirectory(utils) +add_subdirectory(vectorize) diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile index f3637a6..15bffb4 100644 --- a/bindings/ocaml/transforms/Makefile +++ b/bindings/ocaml/transforms/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL := ../../.. -DIRS = scalar_opts ipo vectorize passmgr_builder +DIRS = ipo passmgr_builder scalar_opts utils vectorize ocamldoc: $(Verb) for i in $(DIRS) ; do \ diff --git a/bindings/ocaml/transforms/ipo/CMakeLists.txt b/bindings/ocaml/transforms/ipo/CMakeLists.txt new file mode 100644 index 0000000..4b8784f --- /dev/null +++ b/bindings/ocaml/transforms/ipo/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_ipo + OCAML llvm_ipo + OCAMLDEP llvm + C ipo_ocaml + LLVM ipo) diff --git a/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt b/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt new file mode 100644 index 0000000..b012863 --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_passmgr_builder + OCAML llvm_passmgr_builder + OCAMLDEP llvm + C passmgr_builder_ocaml + LLVM ipo) diff --git a/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt b/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt new file mode 100644 index 0000000..98c7c68 --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_scalar_opts + OCAML llvm_scalar_opts + OCAMLDEP llvm + C scalar_opts_ocaml + LLVM scalaropts) diff --git a/bindings/ocaml/transforms/utils/CMakeLists.txt b/bindings/ocaml/transforms/utils/CMakeLists.txt new file mode 100644 index 0000000..37f3eb7 --- /dev/null +++ b/bindings/ocaml/transforms/utils/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_transform_utils + OCAML llvm_transform_utils + OCAMLDEP llvm + C transform_utils_ocaml + LLVM transformutils) diff --git a/bindings/ocaml/transforms/utils/Makefile b/bindings/ocaml/transforms/utils/Makefile new file mode 100644 index 0000000..76a6f0b --- /dev/null +++ b/bindings/ocaml/transforms/utils/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/utils/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 interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_transform_utils +UsedComponents := transformutils +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/utils/llvm_transform_utils.ml b/bindings/ocaml/transforms/utils/llvm_transform_utils.ml new file mode 100644 index 0000000..135efe2 --- /dev/null +++ b/bindings/ocaml/transforms/utils/llvm_transform_utils.ml @@ -0,0 +1,10 @@ +(*===-- llvm_transform_utils.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 clone_module : Llvm.llmodule -> Llvm.llmodule = "llvm_clone_module" diff --git a/bindings/ocaml/transforms/utils/llvm_transform_utils.mli b/bindings/ocaml/transforms/utils/llvm_transform_utils.mli new file mode 100644 index 0000000..1c2b07c --- /dev/null +++ b/bindings/ocaml/transforms/utils/llvm_transform_utils.mli @@ -0,0 +1,17 @@ +(*===-- llvm_transform_utils.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. + * + *===----------------------------------------------------------------------===*) + +(** Transform Utilities. + + This interface provides an OCaml API for LLVM transform utilities, the + classes in the [LLVMTransformUtils] library. *) + +(** [clone_module m] returns an exact copy of module [m]. + See the [llvm::CloneModule] function. *) +external clone_module : Llvm.llmodule -> Llvm.llmodule = "llvm_clone_module" diff --git a/bindings/ocaml/transforms/utils/transform_utils_ocaml.c b/bindings/ocaml/transforms/utils/transform_utils_ocaml.c new file mode 100644 index 0000000..75b2052 --- /dev/null +++ b/bindings/ocaml/transforms/utils/transform_utils_ocaml.c @@ -0,0 +1,31 @@ +/*===-- 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/Core.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* + * Do not move directly into external. This function is here to pull in + * -lLLVMTransformUtils, which would otherwise be not linked on static builds, + * as ld can't see the reference from OCaml code. + */ + +/* llmodule -> llmodule */ +CAMLprim LLVMModuleRef llvm_clone_module(LLVMModuleRef M) { + return LLVMCloneModule(M); +} diff --git a/bindings/ocaml/transforms/vectorize/CMakeLists.txt b/bindings/ocaml/transforms/vectorize/CMakeLists.txt new file mode 100644 index 0000000..af0ffce --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_vectorize + OCAML llvm_vectorize + OCAMLDEP llvm + C vectorize_ocaml + LLVM vectorize) diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 5204f6c..d646498 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -79,6 +79,7 @@ check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT) check_include_file(mach/mach.h HAVE_MACH_MACH_H) check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H) +check_include_file(histedit.h HAVE_HISTEDIT_H) # size_t must be defined before including cxxabi.h on FreeBSD 10.0. check_cxx_source_compiles(" @@ -110,7 +111,9 @@ if( NOT PURE_WINDOWS ) else() set(HAVE_LIBZ 0) endif() - check_library_exists(edit el_init "" HAVE_LIBEDIT) + if (HAVE_HISTEDIT_H) + check_library_exists(edit el_init "" HAVE_LIBEDIT) + endif() if(LLVM_ENABLE_TERMINFO) set(HAVE_TERMINFO 0) foreach(library tinfo terminfo curses ncurses ncursesw) @@ -160,6 +163,7 @@ if( HAVE_SYS_UIO_H ) check_symbol_exists(writev sys/uio.h HAVE_WRITEV) endif() check_symbol_exists(nearbyintf math.h HAVE_NEARBYINTF) +check_symbol_exists(mallctl malloc_np.h HAVE_MALLCTL) check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO) check_symbol_exists(malloc_zone_statistics malloc/malloc.h HAVE_MALLOC_ZONE_STATISTICS) @@ -198,7 +202,9 @@ if( PURE_WINDOWS ) check_function_exists(_alloca HAVE__ALLOCA) check_function_exists(__alloca HAVE___ALLOCA) check_function_exists(__chkstk HAVE___CHKSTK) + check_function_exists(__chkstk_ms HAVE___CHKSTK_MS) check_function_exists(___chkstk HAVE____CHKSTK) + check_function_exists(___chkstk_ms HAVE____CHKSTK_MS) check_function_exists(__ashldi3 HAVE___ASHLDI3) check_function_exists(__ashrdi3 HAVE___ASHRDI3) @@ -424,6 +430,24 @@ if( MSVC ) set(SHLIBEXT ".lib") set(stricmp "_stricmp") set(strdup "_strdup") + + # See if the DIA SDK is available and usable. + set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK") + + # Due to a bug in MSVC 2013's installation software, it is possible + # for MSVC 2013 to write the DIA SDK into the Visual Studio 2012 + # install directory. If this happens, the installation is corrupt + # and there's nothing we can do. It happens with enough frequency + # though that we should handle it. We do so by simply checking that + # the DIA SDK folder exists. Should this happen you will need to + # uninstall VS 2012 and then re-install VS 2013. + if (IS_DIRECTORY ${MSVC_DIA_SDK_DIR}) + set(HAVE_DIA_SDK 1) + else() + set(HAVE_DIA_SDK 0) + endif() +else() + set(HAVE_DIA_SDK 0) endif( MSVC ) if( PURE_WINDOWS ) @@ -516,3 +540,35 @@ else() endif() endif() endif() + +find_program(GOLD_EXECUTABLE NAMES ld.gold ld DOC "The gold linker") +if(GOLD_EXECUTABLE) + set(LLVM_BINUTILS_INCDIR "" CACHE PATH + "PATH to binutils/include containing plugin-api.h for gold plugin.") +endif() + +include(FindOCaml) +include(AddOCaml) +if(WIN32) + message(STATUS "OCaml bindings disabled.") +else() + find_package(OCaml) + if( NOT OCAML_FOUND ) + message(STATUS "OCaml bindings disabled.") + else() + if( OCAML_VERSION VERSION_LESS "4.00.0" ) + message(STATUS "OCaml bindings disabled, need OCaml >=4.00.0.") + else() + find_ocamlfind_package(ctypes VERSION 0.3 OPTIONAL) + if( HAVE_OCAML_CTYPES ) + message(STATUS "OCaml bindings enabled.") + find_ocamlfind_package(oUnit VERSION 2 OPTIONAL) + set(LLVM_BINDINGS "${LLVM_BINDINGS} ocaml") + else() + message(STATUS "OCaml bindings disabled, need ctypes >=0.3.") + endif() + endif() + endif() +endif() + +string(REPLACE " " ";" LLVM_BINDINGS_LIST "${LLVM_BINDINGS}") diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index bc26f06..7f63644 100644 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -10,7 +10,7 @@ function(llvm_update_compile_flags name) # LLVM_REQUIRES_EH is an internal flag that individual # targets can use to force EH - if(LLVM_REQUIRES_EH OR LLVM_ENABLE_EH) + if((LLVM_REQUIRES_EH OR LLVM_ENABLE_EH) AND NOT CLANG_CL) if(NOT (LLVM_REQUIRES_RTTI OR LLVM_ENABLE_RTTI)) message(AUTHOR_WARNING "Exception handling requires RTTI. Enabling RTTI for ${name}") set(LLVM_REQUIRES_RTTI ON) @@ -22,6 +22,10 @@ function(llvm_update_compile_flags name) list(APPEND LLVM_COMPILE_DEFINITIONS _HAS_EXCEPTIONS=0) list(APPEND LLVM_COMPILE_FLAGS "/EHs-c-") endif() + if (CLANG_CL) + # FIXME: Remove this once clang-cl supports SEH + list(APPEND LLVM_COMPILE_DEFINITIONS "GTEST_HAS_SEH=0") + endif() endif() # LLVM_REQUIRES_RTTI is an internal flag that individual @@ -142,6 +146,17 @@ function(add_llvm_symbol_exports target_name export_file) set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE) endfunction(add_llvm_symbol_exports) +if(NOT WIN32 AND NOT APPLE) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -Wl,--version + OUTPUT_VARIABLE stdout + ERROR_QUIET + ) + if("${stdout}" MATCHES "GNU gold") + set(LLVM_LINKER_IS_GOLD ON) + endif() +endif() + function(add_link_opts target_name) # Pass -O3 to the linker. This enabled different optimizations on different # linkers. @@ -150,12 +165,20 @@ function(add_link_opts target_name) LINK_FLAGS " -Wl,-O3") endif() + if(LLVM_LINKER_IS_GOLD) + # With gold gc-sections is always safe. + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--gc-sections") + # Note that there is a bug with -Wl,--icf=safe so it is not safe + # to enable. See https://sourceware.org/bugzilla/show_bug.cgi?id=17704. + endif() + if(NOT LLVM_NO_DEAD_STRIP) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # ld64's implementation of -dead_strip breaks tools that use plugins. set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dead_strip") - elseif(NOT WIN32) + elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD) # Object files are compiled with -ffunction-data-sections. # Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks # tools that use plugins. Always pass --gc-sections once we require @@ -315,11 +338,11 @@ function(llvm_add_library name) PREFIX "" ) endif() - if (MSVC) - set_target_properties(${name} - PROPERTIES - IMPORT_SUFFIX ".imp") - endif () + + set_target_properties(${name} + PROPERTIES + SOVERSION ${LLVM_VERSION_MAJOR} + VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX}) endif() if(ARG_MODULE OR ARG_SHARED) @@ -394,7 +417,16 @@ macro(add_llvm_library name) EXPORT LLVMExports RUNTIME DESTINATION bin LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} + COMPONENT ${name}) + + if (NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-${name} + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() endif() set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name}) endif() @@ -475,7 +507,16 @@ macro(add_llvm_tool name) if( LLVM_BUILD_TOOLS ) install(TARGETS ${name} EXPORT LLVMExports - RUNTIME DESTINATION bin) + RUNTIME DESTINATION bin + COMPONENT ${name}) + + if (NOT CMAKE_CONFIGURATION_TYPES) + add_custom_target(install-${name} + DEPENDS ${name} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=${name} + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() endif() endif() if( LLVM_BUILD_TOOLS ) @@ -570,12 +611,6 @@ function(add_unittest test_suite test_name) set(EXCLUDE_FROM_ALL ON) endif() - # Visual Studio 2012 only supports up to 8 template parameters in - # std::tr1::tuple by default, but gtest requires 10 - if (MSVC AND MSVC_VERSION EQUAL 1700) - list(APPEND LLVM_COMPILE_DEFINITIONS _VARIADIC_MAX=10) - endif () - include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) if (NOT LLVM_ENABLE_THREADS) list(APPEND LLVM_COMPILE_DEFINITIONS GTEST_HAS_PTHREAD=0) @@ -603,6 +638,36 @@ function(add_unittest test_suite test_name) endif () endfunction() +function(llvm_add_go_executable binary pkgpath) + cmake_parse_arguments(ARG "ALL" "" "DEPENDS;GOFLAGS" ${ARGN}) + + if(LLVM_BINDINGS MATCHES "go") + # FIXME: This should depend only on the libraries Go needs. + get_property(llvmlibs GLOBAL PROPERTY LLVM_LIBS) + set(binpath ${CMAKE_BINARY_DIR}/bin/${binary}${CMAKE_EXECUTABLE_SUFFIX}) + set(cc "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}") + set(cxx "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}") + set(cppflags "") + get_property(include_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + foreach(d ${include_dirs}) + set(cppflags "${cppflags} -I${d}") + endforeach(d) + set(ldflags "${CMAKE_EXE_LINKER_FLAGS}") + add_custom_command(OUTPUT ${binpath} + COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" + ${ARG_GOFLAGS} build -o ${binpath} ${pkgpath} + DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX} + ${llvmlibs} ${ARG_DEPENDS} + COMMENT "Building Go executable ${binary}" + VERBATIM) + if (ARG_ALL) + add_custom_target(${binary} ALL DEPENDS ${binpath}) + else() + add_custom_target(${binary} DEPENDS ${binpath}) + endif() + endif() +endfunction() + # This function provides an automatic way to 'configure'-like generate a file # based on a set of common and custom variables, specifically targeting the # variables needed for the 'lit.site.cfg' files. This function bundles the @@ -675,18 +740,20 @@ function(add_lit_target target comment) foreach(param ${ARG_PARAMS}) list(APPEND LIT_COMMAND --param ${param}) endforeach() - if( ARG_DEPENDS ) + if (ARG_DEFAULT_ARGS) add_custom_target(${target} COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS} COMMENT "${comment}" ${cmake_3_2_USES_TERMINAL} ) - add_dependencies(${target} ${ARG_DEPENDS}) else() add_custom_target(${target} COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, no tools built.") message(STATUS "${target} does nothing.") endif() + if (ARG_DEPENDS) + add_dependencies(${target} ${ARG_DEPENDS}) + endif() # Tests should be excluded from "Build Solution". set_target_properties(${target} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON) diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake new file mode 100644 index 0000000..c58ac9c --- /dev/null +++ b/cmake/modules/AddOCaml.cmake @@ -0,0 +1,201 @@ +# CMake build rules for the OCaml language. +# Assumes FindOCaml is used. +# http://ocaml.org/ +# +# Example usage: +# +# add_ocaml_library(pkg_a OCAML mod_a OCAMLDEP pkg_b C mod_a_stubs PKG ctypes LLVM core) +# +# Unnamed parameters: +# +# * Library name. +# +# Named parameters: +# +# OCAML OCaml module names. Imply presence of a corresponding .ml and .mli files. +# OCAMLDEP Names of libraries this library depends on. +# C C stub sources. Imply presence of a corresponding .c file. +# CFLAGS Additional arguments passed when compiling C stubs. +# PKG Names of ocamlfind packages this library depends on. +# LLVM Names of LLVM libraries this library depends on. +# NOCOPY Do not automatically copy sources (.c, .ml, .mli) from the source directory, +# e.g. if they are generated. +# + +function(add_ocaml_library name) + CMAKE_PARSE_ARGUMENTS(ARG "NOCOPY" "" "OCAML;OCAMLDEP;C;CFLAGS;PKG;LLVM" ${ARGN}) + + set(src ${CMAKE_CURRENT_SOURCE_DIR}) + set(bin ${CMAKE_CURRENT_BINARY_DIR}) + + set(ocaml_pkgs) + foreach( ocaml_pkg ${ARG_PKG} ) + list(APPEND ocaml_pkgs "-package" "${ocaml_pkg}") + endforeach() + + set(sources) + + set(ocaml_inputs) + + set(ocaml_outputs "${bin}/${name}.cma") + if( ARG_C ) + list(APPEND ocaml_outputs + "${bin}/lib${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + if ( BUILD_SHARED_LIBS ) + list(APPEND ocaml_outputs + "${bin}/dll${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + endif() + if( HAVE_OCAMLOPT ) + list(APPEND ocaml_outputs + "${bin}/${name}.cmxa" + "${bin}/${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + endif() + + set(ocaml_flags "-lstdc++" "-ldopt" "-L${LLVM_LIBRARY_DIR}" + "-ccopt" "-L\\$CAMLORIGIN/.." + "-ccopt" "-Wl,-rpath,\\$CAMLORIGIN/.." + ${ocaml_pkgs}) + + foreach( ocaml_dep ${ARG_OCAMLDEP} ) + get_target_property(dep_ocaml_flags "ocaml_${ocaml_dep}" OCAML_FLAGS) + list(APPEND ocaml_flags ${dep_ocaml_flags}) + endforeach() + + if( NOT BUILD_SHARED_LIBS ) + list(APPEND ocaml_flags "-custom") + endif() + + explicit_map_components_to_libraries(llvm_libs ${ARG_LLVM}) + foreach( llvm_lib ${llvm_libs} ) + list(APPEND ocaml_flags "-l${llvm_lib}" ) + endforeach() + + get_property(system_libs TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) + foreach(system_lib ${system_libs}) + list(APPEND ocaml_flags "-l${system_lib}" ) + endforeach() + + string(REPLACE ";" " " ARG_CFLAGS "${ARG_CFLAGS}") + set(c_flags "${ARG_CFLAGS} ${LLVM_DEFINITIONS}") + foreach( include_dir ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR} ) + set(c_flags "${c_flags} -I${include_dir}") + endforeach() + + foreach( ocaml_file ${ARG_OCAML} ) + list(APPEND sources "${ocaml_file}.mli" "${ocaml_file}.ml") + + list(APPEND ocaml_inputs "${bin}/${ocaml_file}.mli" "${bin}/${ocaml_file}.ml") + + list(APPEND ocaml_outputs "${bin}/${ocaml_file}.cmi" "${bin}/${ocaml_file}.cmo") + if( HAVE_OCAMLOPT ) + list(APPEND ocaml_outputs + "${bin}/${ocaml_file}.cmx" + "${bin}/${ocaml_file}${CMAKE_C_OUTPUT_EXTENSION}") + endif() + endforeach() + + foreach( c_file ${ARG_C} ) + list(APPEND sources "${c_file}.c") + + list(APPEND c_inputs "${bin}/${c_file}.c") + list(APPEND c_outputs "${bin}/${c_file}${CMAKE_C_OUTPUT_EXTENSION}") + endforeach() + + if( NOT ARG_NOCOPY ) + foreach( source ${sources} ) + add_custom_command( + OUTPUT "${bin}/${source}" + COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${src}/${source}" "${bin}" + DEPENDS "${src}/${source}" + COMMENT "Copying ${source} to build area") + endforeach() + endif() + + foreach( c_input ${c_inputs} ) + get_filename_component(basename "${c_input}" NAME_WE) + add_custom_command( + OUTPUT "${basename}${CMAKE_C_OUTPUT_EXTENSION}" + COMMAND "${OCAMLFIND}" "ocamlc" "-c" "${c_input}" -ccopt ${c_flags} + DEPENDS "${c_input}" + COMMENT "Building OCaml stub object file ${basename}${CMAKE_C_OUTPUT_EXTENSION}" + VERBATIM) + endforeach() + + set(ocaml_params) + foreach( ocaml_input ${ocaml_inputs} ${c_outputs}) + get_filename_component(filename "${ocaml_input}" NAME) + list(APPEND ocaml_params "${filename}") + endforeach() + + if( APPLE ) + set(ocaml_rpath "@executable_path/../../lib") + elseif( UNIX ) + set(ocaml_rpath "\\$ORIGIN/../../lib") + endif() + list(APPEND ocaml_flags "-ldopt" "-Wl,-rpath,${ocaml_rpath}") + + add_custom_command( + OUTPUT ${ocaml_outputs} + COMMAND "${OCAMLFIND}" "ocamlmklib" "-o" "${name}" ${ocaml_flags} ${ocaml_params} + DEPENDS ${ocaml_inputs} ${c_outputs} + COMMENT "Building OCaml library ${name}" + VERBATIM) + + add_custom_command( + OUTPUT "${bin}/${name}.odoc" + COMMAND "${OCAMLFIND}" "ocamldoc" + "-I" "${bin}" + "-I" "${LLVM_LIBRARY_DIR}/ocaml/" + "-dump" "${bin}/${name}.odoc" + ${ocaml_pkgs} ${ocaml_inputs} + DEPENDS ${ocaml_inputs} + COMMENT "Building OCaml documentation for ${name}" + VERBATIM) + + add_custom_target("ocaml_${name}" ALL DEPENDS ${ocaml_outputs} "${bin}/${name}.odoc") + + set_target_properties("ocaml_${name}" PROPERTIES + OCAML_FLAGS "-I;${bin}") + set_target_properties("ocaml_${name}" PROPERTIES + OCAML_ODOC "${bin}/${name}.odoc") + + foreach( ocaml_dep ${ARG_OCAMLDEP} ) + add_dependencies("ocaml_${name}" "ocaml_${ocaml_dep}") + endforeach() + + foreach( llvm_lib ${llvm_libs} ) + add_dependencies("ocaml_${name}" "${llvm_lib}") + endforeach() + + set(install_files) + set(install_shlibs) + foreach( ocaml_output ${ocaml_outputs} ) + get_filename_component(ext "${ocaml_output}" EXT) + + if( NOT (ext STREQUAL ".cmo" OR + ext STREQUAL CMAKE_C_OUTPUT_EXTENSION OR + ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX) ) + list(APPEND install_files "${ocaml_output}") + elseif( ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX) + list(APPEND install_shlibs "${ocaml_output}") + endif() + endforeach() + + install(FILES ${install_files} + DESTINATION lib/ocaml) + install(FILES ${install_shlibs} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION lib/ocaml) + + foreach( install_file ${install_files} ${install_shlibs} ) + get_filename_component(filename "${install_file}" NAME) + add_custom_command(TARGET "ocaml_${name}" POST_BUILD + COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${install_file}" + "${LLVM_LIBRARY_DIR}/ocaml/" + COMMENT "Copying OCaml library component ${filename} to intermediate area" + VERBATIM) + endforeach() +endfunction() diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt index c87193d..5f3f255 100644 --- a/cmake/modules/CMakeLists.txt +++ b/cmake/modules/CMakeLists.txt @@ -58,7 +58,7 @@ foreach(p ${_count}) get_filename_component(LLVM_INSTALL_PREFIX \"\${LLVM_INSTALL_PREFIX}\" PATH)") endforeach(p) set(LLVM_CONFIG_INCLUDE_DIRS "\${LLVM_INSTALL_PREFIX}/include") -set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/lib") +set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/lib\${LLVM_LIBDIR_SUFFIX}") set(LLVM_CONFIG_CMAKE_DIR "\${LLVM_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}") set(LLVM_CONFIG_TOOLS_BINARY_DIR "\${LLVM_INSTALL_PREFIX}/bin") set(LLVM_CONFIG_EXPORTS_FILE "\${LLVM_CMAKE_DIR}/LLVMExports.cmake") diff --git a/cmake/modules/CheckAtomic.cmake b/cmake/modules/CheckAtomic.cmake index 2ed4819..30a5e31 100644 --- a/cmake/modules/CheckAtomic.cmake +++ b/cmake/modules/CheckAtomic.cmake @@ -2,9 +2,13 @@ INCLUDE(CheckCXXSourceCompiles) -check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) -if (HAVE_LIBATOMIC) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") +check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4) +if( NOT HAVE___ATOMIC_FETCH_ADD_4 ) + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + set(HAVE_LIBATOMIC False) + if( HAVE_LIBATOMIC ) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + endif() endif() CHECK_CXX_SOURCE_COMPILES(" diff --git a/cmake/modules/FindOCaml.cmake b/cmake/modules/FindOCaml.cmake new file mode 100644 index 0000000..8eba212 --- /dev/null +++ b/cmake/modules/FindOCaml.cmake @@ -0,0 +1,103 @@ +# CMake find_package() module for the OCaml language. +# Assumes ocamlfind will be used for compilation. +# http://ocaml.org/ +# +# Example usage: +# +# find_package(OCaml) +# +# If successful, the following variables will be defined: +# OCAMLFIND +# OCAML_VERSION +# OCAML_STDLIB_PATH +# HAVE_OCAMLOPT +# +# Also provides find_ocamlfind_package() macro. +# +# Example usage: +# +# find_ocamlfind_package(ctypes) +# +# In any case, the following variables are defined: +# +# HAVE_OCAML_${pkg} +# +# If successful, the following variables will be defined: +# +# OCAML_${pkg}_VERSION + +include( FindPackageHandleStandardArgs ) + +find_program(OCAMLFIND + NAMES ocamlfind) + +if( OCAMLFIND ) + execute_process( + COMMAND ${OCAMLFIND} ocamlc -version + OUTPUT_VARIABLE OCAML_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND ${OCAMLFIND} ocamlc -where + OUTPUT_VARIABLE OCAML_STDLIB_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND ${OCAMLFIND} ocamlc -version + OUTPUT_QUIET + RESULT_VARIABLE find_ocaml_result) + if( find_ocaml_result EQUAL 0 ) + set(HAVE_OCAMLOPT TRUE) + else() + set(HAVE_OCAMLOPT FALSE) + endif() +endif() + +find_package_handle_standard_args( OCaml DEFAULT_MSG + OCAMLFIND + OCAML_VERSION + OCAML_STDLIB_PATH) + +mark_as_advanced( + OCAMLFIND) + +function(find_ocamlfind_package pkg) + CMAKE_PARSE_ARGUMENTS(ARG "OPTIONAL" "VERSION" "" ${ARGN}) + + execute_process( + COMMAND "${OCAMLFIND}" "query" "${pkg}" "-format" "%v" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_VARIABLE error + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + + if( NOT result EQUAL 0 AND NOT ARG_OPTIONAL ) + message(FATAL_ERROR ${error}) + endif() + + if( result EQUAL 0 ) + set(found TRUE) + else() + set(found FALSE) + endif() + + if( found AND ARG_VERSION ) + if( version VERSION_LESS ARG_VERSION AND ARG_OPTIONAL ) + # If it's optional and the constraint is not satisfied, pretend + # it wasn't found. + set(found FALSE) + elseif( version VERSION_LESS ARG_VERSION ) + message(FATAL_ERROR + "ocamlfind package ${pkg} should have version ${ARG_VERSION} or newer") + endif() + endif() + + string(TOUPPER ${pkg} pkg) + + set(HAVE_OCAML_${pkg} ${found} + PARENT_SCOPE) + + set(OCAML_${pkg}_VERSION ${version} + PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/GetSVN.cmake b/cmake/modules/GetSVN.cmake index 4e32c09..d512bd2 100644 --- a/cmake/modules/GetSVN.cmake +++ b/cmake/modules/GetSVN.cmake @@ -19,13 +19,83 @@ get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH) # Handle strange terminals set(ENV{TERM} "dumb") +macro(get_source_info_svn path revision repository) + # If svn is a bat file, find_program(Subversion) doesn't find it. + # Explicitly search for that here; Subversion_SVN_EXECUTABLE will override + # the find_program call in FindSubversion.cmake. + find_program(Subversion_SVN_EXECUTABLE NAMES svn svn.bat) + + # FindSubversion does not work with symlinks. See PR 8437 + if (NOT IS_SYMLINK "${path}") + find_package(Subversion) + endif() + if (Subversion_FOUND) + subversion_wc_info( ${path} Project ) + if (Project_WC_REVISION) + set(${revision} ${Project_WC_REVISION} PARENT_SCOPE) + endif() + if (Project_WC_URL) + set(${repository} ${Project_WC_URL} PARENT_SCOPE) + endif() + endif() +endmacro() + +macro(get_source_info_git_svn path revision repository) + find_program(git_executable NAMES git git.exe git.cmd) + if (git_executable) + execute_process(COMMAND ${git_executable} svn info + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*" + "\\2" git_svn_rev "${git_output}") + set(${revision} ${git_svn_rev} PARENT_SCOPE) + string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*" + "\\2" git_url "${git_output}") + set(${repository} ${git_url} PARENT_SCOPE) + endif() + endif() +endmacro() + +macro(get_source_info_git path revision repository) + find_program(git_executable NAMES git git.exe git.cmd) + if (git_executable) + execute_process(COMMAND ${git_executable} log -1 --pretty=format:%H + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + set(${revision} ${git_output} PARENT_SCOPE) + endif() + execute_process(COMMAND ${git_executable} remote -v + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + string(REGEX REPLACE "^(.*\n)?[^ \t]+[ \t]+([^ \t\n]+)[ \t]+\\(fetch\\).*" + "\\2" git_url "${git_output}") + set(${repository} "${git_url}" PARENT_SCOPE) + endif() + endif() +endmacro() + +function(get_source_info path revision repository) + if (EXISTS "${path}/.svn") + get_source_info_svn("${path}" revision repository) + elseif (EXISTS "${path}/.git/svn") + get_source_info_git_svn("${path}" revision repository) + elseif (EXISTS "${path}/.git") + get_source_info_git("${path}" revision repository) + endif() +endfunction() + function(append_info name path) - execute_process(COMMAND "${LLVM_DIR}/utils/GetSourceVersion" "${path}" - OUTPUT_VARIABLE revision) + get_source_info("${path}" revision repository) string(STRIP "${revision}" revision) - execute_process(COMMAND "${LLVM_DIR}/utils/GetRepositoryPath" "${path}" - OUTPUT_VARIABLE repository - OUTPUT_STRIP_TRAILING_WHITESPACE) string(STRIP "${repository}" repository) file(APPEND "${HEADER_FILE}.txt" "#define ${name}_REVISION \"${revision}\"\n") diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake index 6cc6d65..fdc4ea0 100644 --- a/cmake/modules/HandleLLVMOptions.cmake +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -21,11 +21,16 @@ if(NOT LLVM_FORCE_USE_OLD_TOOLCHAIN) message(FATAL_ERROR "Host Clang version must be at least 3.1!") endif() - # Also test that we aren't using too old of a version of libstdc++ with the - # Clang compiler. This is tricky as there is no real way to check the - # version of libstdc++ directly. Instead we test for a known bug in - # libstdc++4.6 that is fixed in libstdc++4.7. - if(NOT LLVM_ENABLE_LIBCXX) + if (CMAKE_CXX_SIMULATE_ID MATCHES "MSVC") + if (CMAKE_CXX_SIMULATE_VERSION VERSION_LESS 18.0) + message(FATAL_ERROR "Host Clang must have at least -fms-compatibility-version=18.0") + endif() + set(CLANG_CL 1) + elseif(NOT LLVM_ENABLE_LIBCXX) + # Otherwise, test that we aren't using too old of a version of libstdc++ + # with the Clang compiler. This is tricky as there is no real way to + # check the version of libstdc++ directly. Instead we test for a known + # bug in libstdc++4.6 that is fixed in libstdc++4.7. set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_FLAGS "-std=c++0x") @@ -41,8 +46,11 @@ int main() { return (float)x; }" set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES}) endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0) - message(FATAL_ERROR "Host Visual Studio must be at least 2012 (MSVC 17.0)") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0) + message(FATAL_ERROR "Host Visual Studio must be at least 2013") + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0.31101) + message(WARNING "Host Visual Studio should at least be 2013 Update 4 (MSVC 18.0.31101)" + " due to miscompiles from earlier versions") endif() endif() endif() @@ -79,8 +87,6 @@ if(WIN32) set(LLVM_ON_WIN32 1) set(LLVM_ON_UNIX 0) endif(CYGWIN) - # Maximum path length is 160 for non-unicode paths - set(MAXPATHLEN 160) else(WIN32) if(UNIX) set(LLVM_ON_WIN32 0) @@ -90,8 +96,6 @@ else(WIN32) else(APPLE) set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) endif(APPLE) - # FIXME: Maximum path length is currently set to 'safe' fixed value - set(MAXPATHLEN 2024) else(UNIX) MESSAGE(SEND_ERROR "Unable to determine platform") endif(UNIX) @@ -108,6 +112,15 @@ if(APPLE) set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-flat_namespace -Wl,-undefined -Wl,suppress") endif() +# Pass -Wl,-z,defs. This makes sure all symbols are defined. Otherwise a DSO +# build might work on ELF but fail on MachO/COFF. +if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR + ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND + NOT LLVM_USE_SANITIZER) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs") +endif() + + function(append value) foreach(variable ${ARGN}) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) @@ -399,12 +412,20 @@ if(LLVM_USE_SANITIZER) elseif (LLVM_USE_SANITIZER STREQUAL "Thread") append_common_sanitizer_flags() append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif (LLVM_USE_SANITIZER STREQUAL "Address;Undefined" OR + LLVM_USE_SANITIZER STREQUAL "Undefined;Address") + append_common_sanitizer_flags() + append("-fsanitize=address,undefined -fno-sanitize=vptr,function -fno-sanitize-recover" + CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") endif() else() message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.") endif() + if (LLVM_USE_SANITIZE_COVERAGE) + append("-fsanitize-coverage=4" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() endif() # Turn on -gsplit-dwarf if requested diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index e8c42fc..b24c129 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -152,29 +152,39 @@ function(llvm_map_components_to_libnames out_libs) set(${out_libs} ${expanded_components} PARENT_SCOPE) endfunction() +# Perform a post-order traversal of the dependency graph. +# This duplicates the algorithm used by llvm-config, originally +# in tools/llvm-config/llvm-config.cpp, function ComputeLibsForComponents. +function(expand_topologically name required_libs visited_libs) + list(FIND visited_libs ${name} found) + if( found LESS 0 ) + list(APPEND visited_libs ${name}) + set(visited_libs ${visited_libs} PARENT_SCOPE) + + get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${name}) + foreach( lib_dep ${lib_deps} ) + expand_topologically(${lib_dep} "${required_libs}" "${visited_libs}") + set(required_libs ${required_libs} PARENT_SCOPE) + set(visited_libs ${visited_libs} PARENT_SCOPE) + endforeach() + + list(APPEND required_libs ${name}) + set(required_libs ${required_libs} PARENT_SCOPE) + endif() +endfunction() + # Expand dependencies while topologically sorting the list of libraries: function(llvm_expand_dependencies out_libs) set(expanded_components ${ARGN}) - list(LENGTH expanded_components lst_size) - set(cursor 0) - set(processed) - while( cursor LESS lst_size ) - list(GET expanded_components ${cursor} lib) - get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${lib}) - list(APPEND expanded_components ${lib_deps}) - # Remove duplicates at the front: - list(REVERSE expanded_components) - list(REMOVE_DUPLICATES expanded_components) - list(REVERSE expanded_components) - list(APPEND processed ${lib}) - # Find the maximum index that doesn't have to be re-processed: - while(NOT "${expanded_components}" MATCHES "^${processed}.*" ) - list(REMOVE_AT processed -1) - endwhile() - list(LENGTH processed cursor) - list(LENGTH expanded_components lst_size) - endwhile( cursor LESS lst_size ) - set(${out_libs} ${expanded_components} PARENT_SCOPE) + + set(required_libs) + set(visited_libs) + foreach( lib ${expanded_components} ) + expand_topologically(${lib} "${required_libs}" "${visited_libs}") + endforeach() + + list(REVERSE required_libs) + set(${out_libs} ${required_libs} PARENT_SCOPE) endfunction() function(explicit_map_components_to_libraries out_libs) diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index 780a608..9a9cd85 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -40,6 +40,8 @@ set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) set(LLVM_ON_UNIX @LLVM_ON_UNIX@) set(LLVM_ON_WIN32 @LLVM_ON_WIN32@) +set(LLVM_LIBDIR_SUFFIX @LLVM_LIBDIR_SUFFIX@) + set(LLVM_INCLUDE_DIRS "@LLVM_CONFIG_INCLUDE_DIRS@") set(LLVM_LIBRARY_DIRS "@LLVM_CONFIG_LIBRARY_DIRS@") set(LLVM_DEFINITIONS "-D__STDC_LIMIT_MACROS" "-D__STDC_CONSTANT_MACROS") diff --git a/cmake/modules/LLVMProcessSources.cmake b/cmake/modules/LLVMProcessSources.cmake index 64ebce8..ae1921b 100644 --- a/cmake/modules/LLVMProcessSources.cmake +++ b/cmake/modules/LLVMProcessSources.cmake @@ -28,26 +28,39 @@ macro(add_td_sources srcs) endif() endmacro(add_td_sources) +function(add_header_files_for_glob hdrs_out glob) + file(GLOB hds ${glob}) + set(${hdrs_out} ${hds} PARENT_SCOPE) +endfunction(add_header_files_for_glob) -macro(add_header_files srcs) - file(GLOB hds *.h) - if( hds ) - set_source_files_properties(${hds} PROPERTIES HEADER_FILE_ONLY ON) - list(APPEND ${srcs} ${hds}) - endif() -endmacro(add_header_files) +function(find_all_header_files hdrs_out additional_headerdirs) + add_header_files_for_glob(hds *.h) + list(APPEND all_headers ${hds}) + + foreach(additional_dir ${additional_headerdirs}) + add_header_files_for_glob(hds "${additional_dir}/*.h") + list(APPEND all_headers ${hds}) + add_header_files_for_glob(hds "${additional_dir}/*.inc") + list(APPEND all_headers ${hds}) + endforeach(additional_dir) + + set( ${hdrs_out} ${all_headers} PARENT_SCOPE ) +endfunction(find_all_header_files) function(llvm_process_sources OUT_VAR) - cmake_parse_arguments(ARG "" "" "ADDITIONAL_HEADERS" ${ARGN}) + cmake_parse_arguments(ARG "" "" "ADDITIONAL_HEADERS;ADDITIONAL_HEADER_DIRS" ${ARGN}) set(sources ${ARG_UNPARSED_ARGUMENTS}) llvm_check_source_file_list( ${sources} ) if( MSVC_IDE OR XCODE ) # This adds .td and .h files to the Visual Studio solution: add_td_sources(sources) - add_header_files(sources) + find_all_header_files(hdrs "${ARG_ADDITIONAL_HEADER_DIRS}") + if (hdrs) + set_source_files_properties(${hdrs} PROPERTIES HEADER_FILE_ONLY ON) + endif() set_source_files_properties(${ARG_ADDITIONAL_HEADERS} PROPERTIES HEADER_FILE_ONLY ON) - list(APPEND sources ${ARG_ADDITIONAL_HEADERS}) + list(APPEND sources ${ARG_ADDITIONAL_HEADERS} ${hdrs}) endif() set( ${OUT_VAR} ${sources} PARENT_SCOPE ) diff --git a/cmake/modules/Makefile b/cmake/modules/Makefile index dd31aa7..e38f5a6 100644 --- a/cmake/modules/Makefile +++ b/cmake/modules/Makefile @@ -48,7 +48,7 @@ endif OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake -$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in $(LLVMBuildCMakeFrag) +$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag) $(Echo) 'Generating LLVM CMake package config file' $(Verb) ( \ cat $< | sed \ @@ -73,6 +73,7 @@ $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in $(LLVMBuildCMakeFrag) -e 's/@LLVM_ENABLE_PIC@/'"$(ENABLE_PIC)"'/' \ -e 's/@LLVM_ON_UNIX@/'"$(LLVM_ON_UNIX)"'/' \ -e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \ + -e 's/@LLVM_LIBDIR_SUFFIX@//' \ -e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \ -e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \ -e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \ diff --git a/cmake/platforms/iOS.cmake b/cmake/platforms/iOS.cmake index 4973643..e18ca6b 100644 --- a/cmake/platforms/iOS.cmake +++ b/cmake/platforms/iOS.cmake @@ -18,8 +18,17 @@ IF(NOT DEFINED ENV{SDKROOT}) MESSAGE(FATAL_ERROR "SDKROOT env var must be set: " $ENV{SDKROOT}) ENDIF() +IF(EXISTS $ENV{SDKROOT}) + SET(SDKROOT $ENV{SDKROOT}) +ELSE() + execute_process(COMMAND xcodebuild -version -sdk $ENV{SDKROOT} Path + OUTPUT_VARIABLE SDKROOT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +ENDIF() + IF(NOT CMAKE_C_COMPILER) - execute_process(COMMAND xcrun -sdk iphoneos -find clang + execute_process(COMMAND xcrun -sdk $ENV{SDKROOT} -find clang OUTPUT_VARIABLE CMAKE_C_COMPILER ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -27,21 +36,30 @@ IF(NOT CMAKE_C_COMPILER) ENDIF() IF(NOT CMAKE_CXX_COMPILER) - execute_process(COMMAND xcrun -sdk iphoneos -find clang++ + execute_process(COMMAND xcrun -sdk $ENV{SDKROOT} -find clang++ OUTPUT_VARIABLE CMAKE_CXX_COMPILER ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) message(STATUS "Using c compiler ${CMAKE_CXX_COMPILER}") ENDIF() +IF(NOT CMAKE_AR) + execute_process(COMMAND xcrun -sdk $ENV{SDKROOT} -find ar + OUTPUT_VARIABLE CMAKE_AR_val + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + SET(CMAKE_AR ${CMAKE_AR_val} CACHE FILEPATH "Archiver") + message(STATUS "Using ar ${CMAKE_AR}") +ENDIF() + IF (NOT DEFINED IOS_MIN_TARGET) -execute_process(COMMAND xcodebuild -sdk iphoneos -version SDKVersion +execute_process(COMMAND xcodebuild -sdk $ENV{SDKROOT} -version SDKVersion OUTPUT_VARIABLE IOS_MIN_TARGET ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) ENDIF() -SET(IOS_COMMON_FLAGS "-isysroot $ENV{SDKROOT} -mios-version-min=${IOS_MIN_TARGET}") +SET(IOS_COMMON_FLAGS "-mios-version-min=${IOS_MIN_TARGET}") SET(CMAKE_C_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_cflags" FORCE) SET(CMAKE_CXX_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_cxxflags" FORCE) SET(CMAKE_LINK_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_linkflags" FORCE) diff --git a/configure b/configure index b8cb1e2..cac9bf6 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.6.0svn. +# Generated by GNU Autoconf 2.60 for LLVM 3.7.0svn. # # 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.6.0svn' -PACKAGE_STRING='LLVM 3.6.0svn' +PACKAGE_VERSION='3.7.0svn' +PACKAGE_STRING='LLVM 3.7.0svn' PACKAGE_BUGREPORT='http://llvm.org/bugs/' ac_unique_file="lib/IR/Module.cpp" @@ -1314,7 +1314,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.6.0svn to adapt to many kinds of systems. +\`configure' configures LLVM 3.7.0svn to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1380,7 +1380,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of LLVM 3.6.0svn:";; + short | recursive ) echo "Configuration of LLVM 3.7.0svn:";; esac cat <<\_ACEOF @@ -1550,7 +1550,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -LLVM configure 3.6.0svn +LLVM configure 3.7.0svn generated by GNU Autoconf 2.60 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1566,7 +1566,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.6.0svn, which was +It was created by LLVM $as_me 3.7.0svn, which was generated by GNU Autoconf 2.60. Invocation command line was $ $0 $@ @@ -1921,7 +1921,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu LLVM_VERSION_MAJOR=3 -LLVM_VERSION_MINOR=6 +LLVM_VERSION_MINOR=7 LLVM_VERSION_PATCH=0 LLVM_VERSION_SUFFIX=svn @@ -3966,6 +3966,11 @@ else llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="DragonFly" llvm_cv_platform_type="Unix" ;; + *-*-bitrig*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Bitrig" + llvm_cv_platform_type="Unix" ;; *-*-hpux*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -4052,6 +4057,8 @@ else llvm_cv_target_os_type="NetBSD" ;; *-*-dragonfly*) llvm_cv_target_os_type="DragonFly" ;; + *-*-bitrig*) + llvm_cv_target_os_type="Bitrig" ;; *-*-hpux*) llvm_cv_target_os_type="HP-UX" ;; *-*-interix*) @@ -4074,6 +4081,8 @@ else llvm_cv_target_os_type="NativeClient" ;; *-unknown-eabi*) llvm_cv_target_os_type="Freestanding" ;; + *-*-ps4) + llvm_cv_target_os_type="PS4" ;; *) llvm_cv_target_os_type="Unknown" ;; esac @@ -9908,7 +9917,7 @@ if test "$ac_res" != no; then else echo "Error! You need to have libopagent around." - exit -1 + exit 1 fi @@ -10071,7 +10080,7 @@ if test $ac_cv_header_opagent_h = yes; then else echo "Error! You need to have opagent.h around." - exit -1 + exit 1 fi @@ -15438,6 +15447,91 @@ _ACEOF fi + { echo "$as_me:$LINENO: checking for __chkstk_ms in -lgcc" >&5 +echo $ECHO_N "checking for __chkstk_ms in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___chkstk_ms+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __chkstk_ms (); +int +main () +{ +return __chkstk_ms (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___chkstk_ms=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___chkstk_ms=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___chkstk_ms" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___chkstk_ms" >&6; } +if test $ac_cv_lib_gcc___chkstk_ms = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___CHKSTK_MS 1 +_ACEOF + +fi + { echo "$as_me:$LINENO: checking for ___chkstk in -lgcc" >&5 echo $ECHO_N "checking for ___chkstk in -lgcc... $ECHO_C" >&6; } if test "${ac_cv_lib_gcc____chkstk+set}" = set; then @@ -15523,6 +15617,91 @@ _ACEOF fi + { echo "$as_me:$LINENO: checking for ___chkstk_ms in -lgcc" >&5 +echo $ECHO_N "checking for ___chkstk_ms in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc____chkstk_ms+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ___chkstk_ms (); +int +main () +{ +return ___chkstk_ms (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc____chkstk_ms=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc____chkstk_ms=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc____chkstk_ms" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc____chkstk_ms" >&6; } +if test $ac_cv_lib_gcc____chkstk_ms = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE____CHKSTK_MS 1 +_ACEOF + +fi + { echo "$as_me:$LINENO: checking for __ashldi3 in -lgcc" >&5 echo $ECHO_N "checking for __ashldi3 in -lgcc... $ECHO_C" >&6; } @@ -18458,6 +18637,12 @@ if test "${clang_src_root}" = ""; then clang_src_root="$srcdir/tools/clang" fi if test -f ${clang_src_root}/README.txt; then + +cat >>confdefs.h <<_ACEOF +#define CLANG_LIBDIR_SUFFIX "" +_ACEOF + + configh="include/clang/Config/config.h" doxy="docs/doxygen.cfg" ac_config_headers="$ac_config_headers tools/clang/${configh}:${clang_src_root}/${configh}.in" @@ -18895,7 +19080,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.6.0svn, which was +This file was extended by LLVM $as_me 3.7.0svn, which was generated by GNU Autoconf 2.60. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18948,7 +19133,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -LLVM config.status 3.6.0svn +LLVM config.status 3.7.0svn configured by $0, generated by GNU Autoconf 2.60, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index 34485b5..4b398a4 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -672,7 +672,7 @@ for each library name referenced. MODULE_CODE_GLOBALVAR Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, dllstorageclass]`` +``[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, externally_initialized, dllstorageclass, comdat]`` The ``GLOBALVAR`` record (code 7) marks the declaration or definition of a global variable. The operand fields are: @@ -741,7 +741,7 @@ global variable. The operand fields are: MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix, dllstorageclass]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -784,12 +784,18 @@ 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, +* *prologuedata*: If non-zero, the value index of the prologue data for this function, plus 1. * *dllstorageclass*: An encoding of the :ref:`dllstorageclass` of this function +* *comdat*: An encoding of the COMDAT of this function + +* *prefixdata*: If non-zero, the value index of the prefix data for this function, + plus 1. + + MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/BitSets.rst b/docs/BitSets.rst new file mode 100644 index 0000000..c6ffdbd --- /dev/null +++ b/docs/BitSets.rst @@ -0,0 +1,70 @@ +======= +Bitsets +======= + +This is a mechanism that allows IR modules to co-operatively build pointer +sets corresponding to addresses within a given set of globals. One example +of a use case for this is to allow a C++ program to efficiently verify (at +each call site) that a vtable pointer is in the set of valid vtable pointers +for the type of the class or its derived classes. + +To use the mechanism, a client creates a global metadata node named +``llvm.bitsets``. Each element is a metadata node with three elements: +the first is a metadata string containing an identifier for the bitset, +the second is a global variable and the third is a byte offset into the +global variable. + +This will cause a link-time optimization pass to generate bitsets from the +memory addresses referenced from the elements of the bitset metadata. The pass +will lay out the referenced globals consecutively, so their definitions must +be available at LTO time. The `GlobalLayoutBuilder`_ class is responsible for +laying out the globals efficiently to minimize the sizes of the underlying +bitsets. An intrinsic, :ref:`llvm.bitset.test `, generates code +to test whether a given pointer is a member of a bitset. + +:Example: + +:: + + target datalayout = "e-p:32:32" + + @a = internal global i32 0 + @b = internal global i32 0 + @c = internal global i32 0 + @d = internal global [2 x i32] [i32 0, i32 0] + + !llvm.bitsets = !{!0, !1, !2, !3, !4} + + !0 = !{!"bitset1", i32* @a, i32 0} + !1 = !{!"bitset1", i32* @b, i32 0} + !2 = !{!"bitset2", i32* @b, i32 0} + !3 = !{!"bitset2", i32* @c, i32 0} + !4 = !{!"bitset2", i32* @d, i32 4} + + declare i1 @llvm.bitset.test(i8* %ptr, metadata %bitset) nounwind readnone + + define i1 @foo(i32* %p) { + %pi8 = bitcast i32* %p to i8* + %x = call i1 @llvm.bitset.test(i8* %pi8, metadata !"bitset1") + ret i1 %x + } + + define i1 @bar(i32* %p) { + %pi8 = bitcast i32* %p to i8* + %x = call i1 @llvm.bitset.test(i8* %pi8, metadata !"bitset2") + ret i1 %x + } + + define void @main() { + %a1 = call i1 @foo(i32* @a) ; returns 1 + %b1 = call i1 @foo(i32* @b) ; returns 1 + %c1 = call i1 @foo(i32* @c) ; returns 0 + %a2 = call i1 @bar(i32* @a) ; returns 0 + %b2 = call i1 @bar(i32* @b) ; returns 1 + %c2 = call i1 @bar(i32* @c) ; returns 1 + %d02 = call i1 @bar(i32* getelementptr ([2 x i32]* @d, i32 0, i32 0)) ; returns 0 + %d12 = call i1 @bar(i32* getelementptr ([2 x i32]* @d, i32 0, i32 1)) ; returns 1 + ret void + } + +.. _GlobalLayoutBuilder: http://llvm.org/klaus/llvm/blob/master/include/llvm/Transforms/IPO/LowerBitSets.h diff --git a/docs/CMake.rst b/docs/CMake.rst index 653fa16..4d96466 100644 --- a/docs/CMake.rst +++ b/docs/CMake.rst @@ -26,7 +26,7 @@ Quick start We use here the command-line, non-interactive CMake interface. #. `Download `_ and install - CMake. Version 2.8 is the minimum required. + CMake. Version 2.8.8 is the minimum required. #. Open a shell. Your development tools must be reachable from this shell through the PATH environment variable. @@ -59,6 +59,36 @@ We use here the command-line, non-interactive CMake interface. environment variable, for instance. You can force CMake to use a given build tool, see the `Usage`_ section. +#. After CMake has finished running, proceed to use IDE project files or start + the build from the build directory: + + .. code-block:: console + + $ cmake --build . + + The ``--build`` option tells ``cmake`` to invoke the underlying build + tool (``make``, ``ninja``, ``xcodebuild``, ``msbuild``, etc). + + The underlying build tool can be invoked directly either of course, but + the ``--build`` option is portable. + +#. After LLVM has finished building, install it from the build directory: + + .. code-block:: console + + $ cmake --build . --target install + + The ``--target`` option with ``install`` parameter in addition to + the ``--build`` option tells ``cmake`` to build the ``install`` target. + + It is possible to set a different install prefix at installation time + by invoking the ``cmake_install.cmake`` script generated in the + build directory: + + .. code-block:: console + + $ cmake -DCMAKE_INSTALL_PREFIX=/tmp/llvm -P cmake_install.cmake + .. _Basic CMake usage: .. _Usage: @@ -215,8 +245,8 @@ LLVM-specific variables Build in C++1y mode, if available. Defaults to OFF. **LLVM_ENABLE_ASSERTIONS**:BOOL - Enables code assertions. Defaults to OFF if and only if ``CMAKE_BUILD_TYPE`` - is *Release*. + Enables code assertions. Defaults to ON if and only if ``CMAKE_BUILD_TYPE`` + is *Debug*. **LLVM_ENABLE_EH**:BOOL Build LLVM with exception handling support. This is necessary if you wish to @@ -234,7 +264,7 @@ LLVM-specific variables Enable all compiler warnings. Defaults to ON. **LLVM_ENABLE_PEDANTIC**:BOOL - Enable pedantic mode. This disable compiler specific extensions, is + Enable pedantic mode. This disables compiler specific extensions, if possible. Defaults to ON. **LLVM_ENABLE_WERROR**:BOOL @@ -316,8 +346,8 @@ LLVM-specific variables otherwise this has no effect. **LLVM_DOXYGEN_QCH_FILENAME**:STRING - The filename of the Qt Compressed Help file that will be genrated when - ``-DLLVM_ENABLE_DOXYGEN=ON`` and + The filename of the Qt Compressed Help file that will be generated when + ``-DLLVM_ENABLE_DOXYGEN=ON`` and ``-DLLVM_ENABLE_DOXYGEN_QT_HELP=ON`` are given. Defaults to ``org.llvm.qch``. This option is only useful in combination with @@ -330,7 +360,7 @@ LLVM-specific variables for more information. Defaults to "org.llvm". This option is only useful in combination with ``-DLLVM_ENABLE_DOXYGEN_QT_HELP=ON``; otherwise this has no effect. - + **LLVM_DOXYGEN_QHP_CUST_FILTER_NAME**:STRING See `Qt Help Project`_ for more information. Defaults to the CMake variable ``${PACKAGE_STRING}`` which @@ -429,7 +459,7 @@ and uses them to build a simple application ``simple-tool``. add_definitions(${LLVM_DEFINITIONS}) # Now build our tools - add_excutable(simple-tool tool.cpp) + add_executable(simple-tool tool.cpp) # Find the libraries that correspond to the LLVM components # that we wish to use diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index d310a0a..da27627 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -104,3 +104,46 @@ if (LLVM_ENABLE_SPHINX) endif() endif() + +list(FIND LLVM_BINDINGS_LIST ocaml uses_ocaml) +if( NOT uses_ocaml LESS 0 ) + set(doc_targets + ocaml_llvm + ocaml_llvm_all_backends + ocaml_llvm_analysis + ocaml_llvm_bitreader + ocaml_llvm_bitwriter + ocaml_llvm_executionengine + ocaml_llvm_irreader + ocaml_llvm_linker + ocaml_llvm_target + ocaml_llvm_ipo + ocaml_llvm_passmgr_builder + ocaml_llvm_scalar_opts + ocaml_llvm_transform_utils + ocaml_llvm_vectorize + ) + + foreach(llvm_target ${LLVM_TARGETS_TO_BUILD}) + list(APPEND doc_targets ocaml_llvm_${llvm_target}) + endforeach() + + set(odoc_files) + foreach( doc_target ${doc_targets} ) + get_target_property(odoc_file ${doc_target} OCAML_ODOC) + list(APPEND odoc_files -load ${odoc_file}) + endforeach() + + add_custom_target(ocaml_doc + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + COMMAND ${OCAMLFIND} ocamldoc -d ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + -sort -colorize-code -html ${odoc_files}) + + add_dependencies(ocaml_doc ${doc_targets}) + + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + DESTINATION docs/ocaml/html) + endif() +endif() diff --git a/docs/CodeGenerator.rst b/docs/CodeGenerator.rst index b0a1059..75d40db 100644 --- a/docs/CodeGenerator.rst +++ b/docs/CodeGenerator.rst @@ -464,7 +464,7 @@ code: mov %EAX, %EDX sar %EDX, 31 idiv %ECX - ret + ret This approach is extremely general (if it can handle the X86 architecture, it can handle anything!) and allows all of the target specific knowledge about the @@ -848,6 +848,10 @@ is based on the final SelectionDAG, with nodes that must be scheduled together bundled into a single scheduling-unit node, and with immediate operands and other nodes that aren't relevant for scheduling omitted. +The option ``-filter-view-dags`` allows to select the name of the basic block +that you are interested to visualize and filters all the previous +``view-*-dags`` options. + .. _Build initial DAG: Initial SelectionDAG Construction @@ -1336,7 +1340,7 @@ found before being stored or after being reloaded. If the indirect strategy is used, after all the virtual registers have been mapped to physical registers or stack slots, it is necessary to use a spiller object to place load and store instructions in the code. Every virtual that has -been mapped to a stack slot will be stored to memory after been defined and will +been mapped to a stack slot will be stored to memory after being defined and will be loaded before being used. The implementation of the spiller tries to recycle load/store instructions, avoiding unnecessary instructions. For an example of how to invoke the spiller, see ``RegAllocLinearScan::runOnMachineFunction`` in @@ -1349,7 +1353,7 @@ With very rare exceptions (e.g., function calls), the LLVM machine code instructions are three address instructions. That is, each instruction is expected to define at most one register, and to use at most two registers. However, some architectures use two address instructions. In this case, the -defined register is also one of the used register. For instance, an instruction +defined register is also one of the used registers. For instance, an instruction such as ``ADD %EAX, %EBX``, in X86 is actually equivalent to ``%EAX = %EAX + %EBX``. @@ -1574,7 +1578,7 @@ three important things that you have to implement for your target: correspond to. The MCInsts that are generated by this are fed into the instruction printer or the encoder. -Finally, at your choosing, you can also implement an subclass of MCCodeEmitter +Finally, at your choosing, you can also implement a subclass of MCCodeEmitter which lowers MCInst's into machine code bytes and relocations. This is important if you want to support direct .o file emission, or would like to implement an assembler for your target. diff --git a/docs/CodingStandards.rst b/docs/CodingStandards.rst index 0552c71..221c431 100644 --- a/docs/CodingStandards.rst +++ b/docs/CodingStandards.rst @@ -83,7 +83,7 @@ Supported C++11 Language and Library Features While LLVM, Clang, and LLD use C++11, not all features are available in all of the toolchains which we support. The set of features supported for use in LLVM -is the intersection of those supported in MSVC 2012, GCC 4.7, and Clang 3.1. +is the intersection of those supported in MSVC 2013, GCC 4.7, and Clang 3.1. The ultimate definition of this set is what build bots with those respective toolchains accept. Don't argue with the build bots. However, we have some guidance below to help you know what to expect. @@ -123,6 +123,12 @@ unlikely to be supported by our host compilers. * ``override`` and ``final``: N2928_, N3206_, N3272_ * Atomic operations and the C++11 memory model: N2429_ +* Variadic templates: N2242_ +* Explicit conversion operators: N2437_ +* Defaulted and deleted functions: N2346_ + + * But not defaulted move constructors or move assignment operators, MSVC 2013 + cannot synthesize them. .. _N2118: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html .. _N2439: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm @@ -143,6 +149,9 @@ unlikely to be supported by our host compilers. .. _N3206: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm .. _N3272: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm .. _N2429: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm +.. _N2242: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf +.. _N2437: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf +.. _N2346: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm .. _MSVC-compatible RTTI: http://llvm.org/PR18951 The supported features in the C++11 standard libraries are less well tracked, @@ -251,7 +260,8 @@ The next section in the file is a concise note that defines the license that the file is released under. This makes it perfectly clear what terms the source code can be distributed under and should not be modified in any way. -The main body is a ``doxygen`` comment describing the purpose of the file. It +The main body is a ``doxygen`` comment (identified by the ``///`` comment +marker instead of the usual ``//``) describing the purpose of the file. It should have a ``\brief`` command that describes the file in one or two sentences. Any additional information should be separated by a blank line. If an algorithm is being implemented or something tricky is going on, a reference @@ -281,7 +291,8 @@ happens: does the method return null? Abort? Format your hard disk? Comment Formatting ^^^^^^^^^^^^^^^^^^ -In general, prefer C++ style (``//``) comments. They take less space, require +In general, prefer C++ style comments (``//`` for normal comments, ``///`` for +``doxygen`` documentation comments). They take less space, require less typing, don't have nesting problems, etc. There are a few cases when it is useful to use C style (``/* */``) comments however: @@ -710,7 +721,7 @@ the symbol (e.g., MSVC). This can lead to problems at link time. // Bar isn't POD, but it does look like a struct. struct Bar { int Data; - Foo() : Data(0) { } + Bar() : Data(0) { } }; Do not use Braced Initializer Lists to Call a Constructor diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst index 2708e9d..9c63848 100644 --- a/docs/CommandGuide/lit.rst +++ b/docs/CommandGuide/lit.rst @@ -341,7 +341,7 @@ LOCAL CONFIGURATION FILES ~~~~~~~~~~~~~~~~~~~~~~~~~ When :program:`lit` loads a subdirectory in a test suite, it instantiates a -local test configuration by cloning the configuration for the parent direction +local test configuration by cloning the configuration for the parent directory --- the root of this configuration chain will always be a test suite. Once the test configuration is cloned :program:`lit` checks for a *lit.local.cfg* file in the subdirectory. If present, this file will be loaded and can be used to diff --git a/docs/CompilerWriterInfo.rst b/docs/CompilerWriterInfo.rst index a012c32..2dfdc9b 100644 --- a/docs/CompilerWriterInfo.rst +++ b/docs/CompilerWriterInfo.rst @@ -41,6 +41,8 @@ MIPS * `MIPS Processor Architecture `_ +* `MIPS 64-bit ELF Object File Specification `_ + PowerPC ------- diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst index 64edca7..696b50f 100644 --- a/docs/ExceptionHandling.rst +++ b/docs/ExceptionHandling.rst @@ -64,6 +64,21 @@ handling at the expense of slower execution when no exceptions are thrown. As exceptions are, by their nature, intended for uncommon code paths, DWARF exception handling is generally preferred to SJLJ. +Windows Runtime Exception Handling +----------------------------------- + +Windows runtime based exception handling uses the same basic IR structure as +Itanium ABI based exception handling, but it relies on the personality +functions provided by the native Windows runtime library, ``__CxxFrameHandler3`` +for C++ exceptions: ``__C_specific_handler`` for 64-bit SEH or +``_frame_handler3/4`` for 32-bit SEH. This results in a very different +execution model and requires some minor modifications to the initial IR +representation and a significant restructuring just before code generation. + +General information about the Windows x64 exception handling mechanism can be +found at `MSDN Exception Handling (x64) +`_. + Overview -------- @@ -263,9 +278,9 @@ there are no catches or filters that require it to. exceptions and throws a third. When all cleanups are finished, if the exception is not handled by the current -function, resume unwinding by calling the `resume -instruction `_, passing in the result of the -``landingpad`` instruction for the original landing pad. +function, resume unwinding by calling the :ref:`resume instruction `, +passing in the result of the ``landingpad`` instruction for the original +landing pad. Throw Filters ------------- @@ -306,6 +321,97 @@ the selector results they understand and then resume exception propagation with the `resume instruction `_ if none of the conditions match. +C++ Exception Handling using the Windows Runtime +================================================= + +(Note: Windows C++ exception handling support is a work in progress and is + not yet fully implemented. The text below describes how it will work + when completed.) + +The Windows runtime function for C++ exception handling uses a multi-phase +approach. When an exception occurs it searches the current callstack for a +frame that has a handler for the exception. If a handler is found, it then +calls the cleanup handler for each frame above the handler which has a +cleanup handler before calling the catch handler. These calls are all made +from a stack context different from the original frame in which the handler +is defined. Therefore, it is necessary to outline these handlers from their +original context before code generation. + +Catch handlers are called with a pointer to the handler itself as the first +argument and a pointer to the parent function's stack frame as the second +argument. The catch handler uses the `llvm.recoverframe +`_ to get a +pointer to a frame allocation block that is created in the parent frame using +the `llvm.allocateframe +`_ intrinsic. +The ``WinEHPrepare`` pass will have created a structure definition for the +contents of this block. The first two members of the structure will always be +(1) a 32-bit integer that the runtime uses to track the exception state of the +parent frame for the purposes of handling chained exceptions and (2) a pointer +to the object associated with the exception (roughly, the parameter of the +catch clause). These two members will be followed by any frame variables from +the parent function which must be accessed in any of the functions unwind or +catch handlers. The catch handler returns the address at which execution +should continue. + +Cleanup handlers perform any cleanup necessary as the frame goes out of scope, +such as calling object destructors. The runtime handles the actual unwinding +of the stack. If an exception occurs in a cleanup handler the runtime manages +termination of the process. Cleanup handlers are called with the same arguments +as catch handlers (a pointer to the handler and a pointer to the parent stack +frame) and use the same mechanism described above to access frame variables +in the parent function. Cleanup handlers do not return a value. + +The IR generated for Windows runtime based C++ exception handling is initially +very similar to the ``landingpad`` mechanism described above. Calls to +libc++abi functions (such as ``__cxa_begin_catch``/``__cxa_end_catch`` and +``__cxa_throw_exception`` are replaced with calls to intrinsics or Windows +runtime functions (such as ``llvm.eh.begincatch``/``llvm.eh.endcatch`` and +``__CxxThrowException``). + +During the WinEHPrepare pass, the handler functions are outlined into handler +functions and the original landing pad code is replaced with a call to the +``llvm.eh.actions`` intrinsic that describes the order in which handlers will +be processed from the logical location of the landing pad and an indirect +branch to the return value of the ``llvm.eh.actions`` intrinsic. The +``llvm.eh.actions`` intrinsic is defined as returning the address at which +execution will continue. This is a temporary construct which will be removed +before code generation, but it allows for the accurate tracking of control +flow until then. + +A typical landing pad will look like this after outlining: + +.. code-block:: llvm + + lpad: + %vals = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) + cleanup + catch i8* bitcast (i8** @_ZTIi to i8*) + catch i8* bitcast (i8** @_ZTIf to i8*) + %recover = call i8* (...)* @llvm.eh.actions( + i32 3, i8* bitcast (i8** @_ZTIi to i8*), i8* (i8*, i8*)* @_Z4testb.catch.1) + i32 2, i8* null, void (i8*, i8*)* @_Z4testb.cleanup.1) + i32 1, i8* bitcast (i8** @_ZTIf to i8*), i8* (i8*, i8*)* @_Z4testb.catch.0) + i32 0, i8* null, void (i8*, i8*)* @_Z4testb.cleanup.0) + indirectbr i8* %recover, [label %try.cont1, label %try.cont2] + +In this example, the landing pad represents an exception handling context with +two catch handlers and a cleanup handler that have been outlined. If an +exception is thrown with a type that matches ``_ZTIi``, the ``_Z4testb.catch.1`` +handler will be called an no clean-up is needed. If an exception is thrown +with a type that matches ``_ZTIf``, first the ``_Z4testb.cleanup.1`` handler +will be called to perform unwind-related cleanup, then the ``_Z4testb.catch.1`` +handler will be called. If an exception is throw which does not match either +of these types and the exception is handled by another frame further up the +call stack, first the ``_Z4testb.cleanup.1`` handler will be called, then the +``_Z4testb.cleanup.0`` handler (which corresponds to a different scope) will be +called, and exception handling will continue at the next frame in the call +stack will be called. One of the catch handlers will return the address of +``%try.cont1`` in the parent function and the other will return the address of +``%try.cont2``, meaning that execution continues at one of those blocks after +an exception is caught. + + Exception Handling Intrinsics ============================= @@ -329,6 +435,70 @@ function. This value can be used to compare against the result of Uses of this intrinsic are generated by the C++ front-end. +.. _llvm.eh.begincatch: + +``llvm.eh.begincatch`` +---------------------- + +.. code-block:: llvm + + i8* @llvm.eh.begincatch(i8* %exn) + + +This intrinsic marks the beginning of catch handling code within the blocks +following a ``landingpad`` instruction. The exact behavior of this function +depends on the compilation target and the personality function associated +with the ``landingpad`` instruction. + +The argument to this intrinsic is a pointer that was previously extracted from +the aggregate return value of the ``landingpad`` instruction. The return +value of the intrinsic is a pointer to the exception object to be used by the +catch code. This pointer is returned as an ``i8*`` value, but the actual type +of the object will depend on the exception that was thrown. + +Uses of this intrinsic are generated by the C++ front-end. Many targets will +use implementation-specific functions (such as ``__cxa_begin_catch``) instead +of this intrinsic. The intrinsic is provided for targets that require a more +abstract interface. + +When used in the native Windows C++ exception handling implementation, this +intrinsic serves as a placeholder to delimit code before a catch handler is +outlined. When the handler is is outlined, this intrinsic will be replaced +by instructions that retrieve the exception object pointer from the frame +allocation block. + + +.. _llvm.eh.endcatch: + +``llvm.eh.endcatch`` +---------------------- + +.. code-block:: llvm + + void @llvm.eh.endcatch() + + +This intrinsic marks the end of catch handling code within the current block, +which will be a successor of a block which called ``llvm.eh.begincatch''. +The exact behavior of this function depends on the compilation target and the +personality function associated with the corresponding ``landingpad`` +instruction. + +There may be more than one call to ``llvm.eh.endcatch`` for any given call to +``llvm.eh.begincatch`` with each ``llvm.eh.endcatch`` call corresponding to the +end of a different control path. All control paths following a call to +``llvm.eh.begincatch`` must reach a call to ``llvm.eh.endcatch``. + +Uses of this intrinsic are generated by the C++ front-end. Many targets will +use implementation-specific functions (such as ``__cxa_begin_catch``) instead +of this intrinsic. The intrinsic is provided for targets that require a more +abstract interface. + +When used in the native Windows C++ exception handling implementation, this +intrinsic serves as a placeholder to delimit code before a catch handler is +outlined. After the handler is outlined, this intrinsic is simply removed. + + SJLJ Intrinsics --------------- diff --git a/docs/ExtendingLLVM.rst b/docs/ExtendingLLVM.rst index 60cbf01..2552c07 100644 --- a/docs/ExtendingLLVM.rst +++ b/docs/ExtendingLLVM.rst @@ -58,7 +58,7 @@ function and then be turned into an instruction if warranted. If it is possible to constant fold your intrinsic, add support to it in the ``canConstantFoldCallTo`` and ``ConstantFoldCall`` functions. -#. ``llvm/test/Regression/*``: +#. ``llvm/test/*``: Add test cases for your test cases to the test suite @@ -164,10 +164,10 @@ complicated behavior in a single node (rotate). #. TODO: document complex patterns. -#. ``llvm/test/Regression/CodeGen/*``: +#. ``llvm/test/CodeGen/*``: Add test cases for your new node to the test suite. - ``llvm/test/Regression/CodeGen/X86/bswap.ll`` is a good example. + ``llvm/test/CodeGen/X86/bswap.ll`` is a good example. Adding a new instruction ======================== @@ -217,7 +217,7 @@ Adding a new instruction add support for your instruction to code generators, or add a lowering pass. -#. ``llvm/test/Regression/*``: +#. ``llvm/test/*``: add your test cases to the test suite. diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst index 49d3496..a1557fc 100644 --- a/docs/GarbageCollection.rst +++ b/docs/GarbageCollection.rst @@ -1,13 +1,82 @@ ===================================== -Accurate Garbage Collection with LLVM +Garbage Collection with LLVM ===================================== .. contents:: :local: +Abstract +======== + +This document covers how to integrate LLVM into a compiler for a language which +supports garbage collection. **Note that LLVM itself does not provide a +garbage collector.** You must provide your own. + +Quick Start +============ + +First, you should pick a collector strategy. LLVM includes a number of built +in ones, but you can also implement a loadable plugin with a custom definition. +Note that the collector strategy is a description of how LLVM should generate +code such that it interacts with your collector and runtime, not a description +of the collector itself. + +Next, mark your generated functions as using your chosen collector strategy. +From c++, you can call: + +.. code-block:: c++ + + F.setGC(); + + +This will produce IR like the following fragment: + +.. code-block:: llvm + + define void @foo() gc "" { ... } + + +When generating LLVM IR for your functions, you will need to: + +* Use ``@llvm.gcread`` and/or ``@llvm.gcwrite`` in place of standard load and + store instructions. These intrinsics are used to represent load and store + barriers. If you collector does not require such barriers, you can skip + this step. + +* Use the memory allocation routines provided by your garbage collector's + runtime library. + +* If your collector requires them, generate type maps according to your + runtime's binary interface. LLVM is not involved in the process. In + particular, the LLVM type system is not suitable for conveying such + information though the compiler. + +* Insert any coordination code required for interacting with your collector. + Many collectors require running application code to periodically check a + flag and conditionally call a runtime function. This is often referred to + as a safepoint poll. + +You will need to identify roots (i.e. references to heap objects your collector +needs to know about) in your generated IR, so that LLVM can encode them into +your final stack maps. Depending on the collector strategy chosen, this is +accomplished by using either the ``@llvm.gcroot`` intrinsics or an +``gc.statepoint`` relocation sequence. + +Don't forget to create a root for each intermediate value that is generated when +evaluating an expression. In ``h(f(), g())``, the result of ``f()`` could +easily be collected if evaluating ``g()`` triggers a collection. + +Finally, you need to link your runtime library with the generated program +executable (for a static compiler) or ensure the appropriate symbols are +available for the runtime linker (for a JIT compiler). + + Introduction ============ +What is Garbage Collection? +--------------------------- + Garbage collection is a widely used technique that frees the programmer from having to know the lifetimes of heap objects, making software easier to produce and maintain. Many programming languages rely on garbage collection for @@ -59,31 +128,34 @@ instance, the intrinsics permit: * generational collectors -* reference counting - * incremental collectors * concurrent collectors * cooperative collectors -We hope that the primitive support built into the LLVM IR is sufficient to -support a broad class of garbage collected languages including Scheme, ML, Java, -C#, Perl, Python, Lua, Ruby, other scripting languages, and more. +* reference counting + +We hope that the support built into the LLVM IR is sufficient to support a +broad class of garbage collected languages including Scheme, ML, Java, C#, +Perl, Python, Lua, Ruby, other scripting languages, and more. -However, LLVM does not itself provide a garbage collector --- this should be -part of your language's runtime library. LLVM provides a framework for compile -time :ref:`code generation plugins `. The role of these plugins is to +Note that LLVM **does not itself provide a garbage collector** --- this should +be part of your language's runtime library. LLVM provides a framework for +describing the garbage collectors requirements to the compiler. In particular, +LLVM provides support for generating stack maps at call sites, polling for a +safepoint, and emitting load and store barriers. You can also extend LLVM - +possibly through a loadable :ref:`code generation plugins ` - to generate code and data structures which conforms to the *binary interface* specified by the *runtime library*. This is similar to the relationship between LLVM and DWARF debugging info, for example. The difference primarily lies in the lack of an established standard in the domain of garbage collection --- thus -the plugins. +the need for a flexible extension mechanism. The aspects of the binary interface with which LLVM's GC support is concerned are: -* Creation of GC-safe points within code where collection is allowed to execute +* Creation of GC safepoints within code where collection is allowed to execute safely. * Computation of the stack map. For each safe point in the code, object @@ -111,205 +183,63 @@ There are additional areas that LLVM does not directly address: In general, LLVM's support for GC does not include features which can be adequately addressed with other features of the IR and does not specify a particular binary interface. On the plus side, this means that you should be -able to integrate LLVM with an existing runtime. On the other hand, it leaves a -lot of work for the developer of a novel language. However, it's easy to get -started quickly and scale up to a more sophisticated implementation as your -compiler matures. - -Getting started -=============== - -Using a GC with LLVM implies many things, for example: - -* Write a runtime library or find an existing one which implements a GC heap. - - #. Implement a memory allocator. - - #. Design a binary interface for the stack map, used to identify references - within a stack frame on the machine stack.\* - - #. Implement a stack crawler to discover functions on the call stack.\* - - #. Implement a registry for global roots. - - #. Design a binary interface for type maps, used to identify references - within heap objects. - - #. Implement a collection routine bringing together all of the above. - -* Emit compatible code from your compiler. - - * Initialization in the main function. - - * Use the ``gc "..."`` attribute to enable GC code generation (or - ``F.setGC("...")``). - - * Use ``@llvm.gcroot`` to mark stack roots. - - * Use ``@llvm.gcread`` and/or ``@llvm.gcwrite`` to manipulate GC references, - if necessary. - - * Allocate memory using the GC allocation routine provided by the runtime - library. - - * Generate type maps according to your runtime's binary interface. - -* Write a compiler plugin to interface LLVM with the runtime library.\* - - * Lower ``@llvm.gcread`` and ``@llvm.gcwrite`` to appropriate code - sequences.\* - - * Compile LLVM's stack map to the binary form expected by the runtime. - -* Load the plugin into the compiler. Use ``llc -load`` or link the plugin - statically with your language's compiler.\* - -* Link program executables with the runtime. - -To help with several of these tasks (those indicated with a \*), LLVM includes a -highly portable, built-in ShadowStack code generator. It is compiled into -``llc`` and works even with the interpreter and C backends. - -In your compiler ----------------- - -To turn the shadow stack on for your functions, first call: - -.. code-block:: c++ - - F.setGC("shadow-stack"); - -for each function your compiler emits. Since the shadow stack is built into -LLVM, you do not need to load a plugin. - -Your compiler must also use ``@llvm.gcroot`` as documented. Don't forget to -create a root for each intermediate value that is generated when evaluating an -expression. In ``h(f(), g())``, the result of ``f()`` could easily be collected -if evaluating ``g()`` triggers a collection. - -There's no need to use ``@llvm.gcread`` and ``@llvm.gcwrite`` over plain -``load`` and ``store`` for now. You will need them when switching to a more -advanced GC. - -In your runtime ---------------- - -The shadow stack doesn't imply a memory allocation algorithm. A semispace -collector or building atop ``malloc`` are great places to start, and can be -implemented with very little code. - -When it comes time to collect, however, your runtime needs to traverse the stack -roots, and for this it needs to integrate with the shadow stack. Luckily, doing -so is very simple. (This code is heavily commented to help you understand the -data structure, but there are only 20 lines of meaningful code.) - -.. code-block:: c++ - - /// @brief The map for a single function's stack frame. One of these is - /// compiled as constant data into the executable for each function. - /// - /// Storage of metadata values is elided if the %metadata parameter to - /// @llvm.gcroot is null. - struct FrameMap { - int32_t NumRoots; //< Number of roots in stack frame. - int32_t NumMeta; //< Number of metadata entries. May be < NumRoots. - const void *Meta[0]; //< Metadata for each root. - }; - - /// @brief A link in the dynamic shadow stack. One of these is embedded in - /// the stack frame of each function on the call stack. - struct StackEntry { - StackEntry *Next; //< Link to next stack entry (the caller's). - const FrameMap *Map; //< Pointer to constant FrameMap. - void *Roots[0]; //< Stack roots (in-place array). - }; - - /// @brief The head of the singly-linked list of StackEntries. Functions push - /// and pop onto this in their prologue and epilogue. - /// - /// Since there is only a global list, this technique is not threadsafe. - StackEntry *llvm_gc_root_chain; - - /// @brief Calls Visitor(root, meta) for each GC root on the stack. - /// root and meta are exactly the values passed to - /// @llvm.gcroot. - /// - /// Visitor could be a function to recursively mark live objects. Or it - /// might copy them to another heap or generation. - /// - /// @param Visitor A function to invoke for every GC root on the stack. - void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) { - for (StackEntry *R = llvm_gc_root_chain; R; R = R->Next) { - unsigned i = 0; - - // For roots [0, NumMeta), the metadata pointer is in the FrameMap. - for (unsigned e = R->Map->NumMeta; i != e; ++i) - Visitor(&R->Roots[i], R->Map->Meta[i]); - - // For roots [NumMeta, NumRoots), the metadata pointer is null. - for (unsigned e = R->Map->NumRoots; i != e; ++i) - Visitor(&R->Roots[i], NULL); - } - } - -About the shadow stack ----------------------- - -Unlike many GC algorithms which rely on a cooperative code generator to compile -stack maps, this algorithm carefully maintains a linked list of stack roots -[:ref:`Henderson2002 `]. This so-called "shadow stack" mirrors the -machine stack. Maintaining this data structure is slower than using a stack map -compiled into the executable as constant data, but has a significant portability -advantage because it requires no special support from the target code generator, -and does not require tricky platform-specific code to crawl the machine stack. - -The tradeoff for this simplicity and portability is: - -* High overhead per function call. - -* Not thread-safe. - -Still, it's an easy way to get started. After your compiler and runtime are up -and running, writing a :ref:`plugin ` will allow you to take advantage -of :ref:`more advanced GC features ` of LLVM in order to -improve performance. +able to integrate LLVM with an existing runtime. On the other hand, it can +have the effect of leaving a lot of work for the developer of a novel +language. We try to mitigate this by providing built in collector strategy +descriptions that can work with many common collector designs and easy +extension points. If you don't already have a specific binary interface +you need to support, we recommend trying to use one of these built in collector +strategies. .. _gc_intrinsics: -IR features -=========== +LLVM IR Features +================ This section describes the garbage collection facilities provided by the :doc:`LLVM intermediate representation `. The exact behavior of these -IR features is specified by the binary interface implemented by a :ref:`code -generation plugin `, not by this document. - -These facilities are limited to those strictly necessary; they are not intended -to be a complete interface to any garbage collector. A program will need to -interface with the GC library using the facilities provided by that program. +IR features is specified by the selected :ref:`GC strategy description +`. Specifying GC code generation: ``gc "..."`` ------------------------------------------- .. code-block:: llvm - define ty @name(...) gc "name" { ... + define @name(...) gc "name" { ... } -The ``gc`` function attribute is used to specify the desired GC style to the +The ``gc`` function attribute is used to specify the desired GC strategy to the compiler. Its programmatic equivalent is the ``setGC`` method of ``Function``. -Setting ``gc "name"`` on a function triggers a search for a matching code -generation plugin "*name*"; it is that plugin which defines the exact nature of -the code generated to support GC. If none is found, the compiler will raise an -error. +Setting ``gc "name"`` on a function triggers a search for a matching subclass +of GCStrategy. Some collector strategies are built in. You can add others +using either the loadable plugin mechanism, or by patching your copy of LLVM. +It is the selected GC strategy which defines the exact nature of the code +generated to support GC. If none is found, the compiler will raise an error. Specifying the GC style on a per-function basis allows LLVM to link together programs that use different garbage collection algorithms (or none at all). .. _gcroot: -Identifying GC roots on the stack: ``llvm.gcroot`` --------------------------------------------------- +Identifying GC roots on the stack +---------------------------------- + +LLVM currently supports two different mechanisms for describing references in +compiled code at safepoints. ``llvm.gcroot`` is the older mechanism; +``gc.statepoint`` has been added more recently. At the moment, you can choose +either implementation (on a per :ref:`GC strategy ` basis). Longer +term, we will probably either migrate away from ``llvm.gcroot`` entirely, or +substantially merge their implementations. Note that most new development +work is focused on ``gc.statepoint``. + +Using ``gc.statepoint`` +^^^^^^^^^^^^^^^^^^^^^^^^ +:doc:`This page ` contains detailed documentation for +``gc.statepoint``. + +Using ``llvm.gcwrite`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: llvm @@ -317,24 +247,27 @@ Identifying GC roots on the stack: ``llvm.gcroot`` The ``llvm.gcroot`` intrinsic is used to inform LLVM that a stack variable references an object on the heap and is to be tracked for garbage collection. -The exact impact on generated code is specified by a :ref:`compiler plugin -`. All calls to ``llvm.gcroot`` **must** reside inside the first basic -block. +The exact impact on generated code is specified by the Function's selected +:ref:`GC strategy `. All calls to ``llvm.gcroot`` **must** reside +inside the first basic block. -A compiler which uses mem2reg to raise imperative code using ``alloca`` into SSA -form need only add a call to ``@llvm.gcroot`` for those variables which a -pointers into the GC heap. +The first argument **must** be a value referring to an alloca instruction or a +bitcast of an alloca. The second contains a pointer to metadata that should be +associated with the pointer, and **must** be a constant or global value +address. If your target collector uses tags, use a null pointer for metadata. + +A compiler which performs manual SSA construction **must** ensure that SSA +values representing GC references are stored in to the alloca passed to the +respective ``gcroot`` before every call site and reloaded after every call. +A compiler which uses mem2reg to raise imperative code using ``alloca`` into +SSA form need only add a call to ``@llvm.gcroot`` for those variables which +are pointers into the GC heap. It is also important to mark intermediate values with ``llvm.gcroot``. For example, consider ``h(f(), g())``. Beware leaking the result of ``f()`` in the case that ``g()`` triggers a collection. Note, that stack variables must be initialized and marked with ``llvm.gcroot`` in function's prologue. -The first argument **must** be a value referring to an alloca instruction or a -bitcast of an alloca. The second contains a pointer to metadata that should be -associated with the pointer, and **must** be a constant or global value -address. If your target collector uses tags, use a null pointer for metadata. - The ``%metadata`` argument can be used to avoid requiring heap objects to have 'isa' pointers or tag bits. [Appel89_, Goldberg91_, Tolmach94_] If specified, its value will be tracked along with the location of the pointer in the stack @@ -407,12 +340,18 @@ pointer: %derived = getelementptr %object, i32 0, i32 2, i32 %n LLVM does not enforce this relationship between the object and derived pointer -(although a :ref:`plugin ` might). However, it would be an unusual -collector that violated it. +(although a particular :ref:`collector strategy ` might). However, it +would be an unusual collector that violated it. + +The use of these intrinsics is naturally optional if the target GC does not +require the corresponding barrier. The GC strategy used with such a collector +should replace the intrinsic calls with the corresponding ``load`` or +``store`` instruction if they are used. -The use of these intrinsics is naturally optional if the target GC does require -the corresponding barrier. Such a GC plugin will replace the intrinsic calls -with the corresponding ``load`` or ``store`` instruction if they are used. +One known deficiency with the current design is that the barrier intrinsics do +not include the size or alignment of the underlying operation performed. It is +currently assumed that the operation is of pointer size and the alignment is +assumed to be the target machine's default alignment. Write barrier: ``llvm.gcwrite`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -423,8 +362,8 @@ Write barrier: ``llvm.gcwrite`` For write barriers, LLVM provides the ``llvm.gcwrite`` intrinsic function. It has exactly the same semantics as a non-volatile ``store`` to the derived -pointer (the third argument). The exact code generated is specified by a -compiler :ref:`plugin `. +pointer (the third argument). The exact code generated is specified by the +Function's selected :ref:`GC strategy `. Many important algorithms require write barriers, including generational and concurrent collectors. Additionally, write barriers could be used to implement @@ -439,16 +378,189 @@ Read barrier: ``llvm.gcread`` For read barriers, LLVM provides the ``llvm.gcread`` intrinsic function. It has exactly the same semantics as a non-volatile ``load`` from the derived pointer -(the second argument). The exact code generated is specified by a -:ref:`compiler plugin `. +(the second argument). The exact code generated is specified by the Function's +selected :ref:`GC strategy `. Read barriers are needed by fewer algorithms than write barriers, and may have a greater performance impact since pointer reads are more frequent than writes. .. _plugin: +.. _builtin-gc-strategies: + +Built In GC Strategies +====================== + +LLVM includes built in support for several varieties of garbage collectors. + +The Shadow Stack GC +---------------------- + +To use this collector strategy, mark your functions with: + +.. code-block:: c++ + + F.setGC("shadow-stack"); + +Unlike many GC algorithms which rely on a cooperative code generator to compile +stack maps, this algorithm carefully maintains a linked list of stack roots +[:ref:`Henderson2002 `]. This so-called "shadow stack" mirrors the +machine stack. Maintaining this data structure is slower than using a stack map +compiled into the executable as constant data, but has a significant portability +advantage because it requires no special support from the target code generator, +and does not require tricky platform-specific code to crawl the machine stack. + +The tradeoff for this simplicity and portability is: + +* High overhead per function call. + +* Not thread-safe. + +Still, it's an easy way to get started. After your compiler and runtime are up +and running, writing a :ref:`plugin ` will allow you to take advantage +of :ref:`more advanced GC features ` of LLVM in order to +improve performance. + + +The shadow stack doesn't imply a memory allocation algorithm. A semispace +collector or building atop ``malloc`` are great places to start, and can be +implemented with very little code. + +When it comes time to collect, however, your runtime needs to traverse the stack +roots, and for this it needs to integrate with the shadow stack. Luckily, doing +so is very simple. (This code is heavily commented to help you understand the +data structure, but there are only 20 lines of meaningful code.) + +.. code-block:: c++ + + /// @brief The map for a single function's stack frame. One of these is + /// compiled as constant data into the executable for each function. + /// + /// Storage of metadata values is elided if the %metadata parameter to + /// @llvm.gcroot is null. + struct FrameMap { + int32_t NumRoots; //< Number of roots in stack frame. + int32_t NumMeta; //< Number of metadata entries. May be < NumRoots. + const void *Meta[0]; //< Metadata for each root. + }; + + /// @brief A link in the dynamic shadow stack. One of these is embedded in + /// the stack frame of each function on the call stack. + struct StackEntry { + StackEntry *Next; //< Link to next stack entry (the caller's). + const FrameMap *Map; //< Pointer to constant FrameMap. + void *Roots[0]; //< Stack roots (in-place array). + }; + + /// @brief The head of the singly-linked list of StackEntries. Functions push + /// and pop onto this in their prologue and epilogue. + /// + /// Since there is only a global list, this technique is not threadsafe. + StackEntry *llvm_gc_root_chain; + + /// @brief Calls Visitor(root, meta) for each GC root on the stack. + /// root and meta are exactly the values passed to + /// @llvm.gcroot. + /// + /// Visitor could be a function to recursively mark live objects. Or it + /// might copy them to another heap or generation. + /// + /// @param Visitor A function to invoke for every GC root on the stack. + void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) { + for (StackEntry *R = llvm_gc_root_chain; R; R = R->Next) { + unsigned i = 0; + + // For roots [0, NumMeta), the metadata pointer is in the FrameMap. + for (unsigned e = R->Map->NumMeta; i != e; ++i) + Visitor(&R->Roots[i], R->Map->Meta[i]); + + // For roots [NumMeta, NumRoots), the metadata pointer is null. + for (unsigned e = R->Map->NumRoots; i != e; ++i) + Visitor(&R->Roots[i], NULL); + } + } + + +The 'Erlang' and 'Ocaml' GCs +----------------------------- + +LLVM ships with two example collectors which leverage the ``gcroot`` +mechanisms. To our knowledge, these are not actually used by any language +runtime, but they do provide a reasonable starting point for someone interested +in writing an ``gcroot`` compatible GC plugin. In particular, these are the +only in tree examples of how to produce a custom binary stack map format using +a ``gcroot`` strategy. + +As there names imply, the binary format produced is intended to model that +used by the Erlang and OCaml compilers respectively. + + +The Statepoint Example GC +------------------------- + +.. code-block:: c++ + + F.setGC("statepoint-example"); + +This GC provides an example of how one might use the infrastructure provided +by ``gc.statepoint``. This example GC is compatible with the +:ref:`PlaceSafepoints` and :ref:`RewriteStatepointsForGC` utility passes +which simplify ``gc.statepoint`` sequence insertion. If you need to build a +custom GC strategy around the ``gc.statepoints`` mechanisms, it is recommended +that you use this one as a starting point. + +This GC strategy does not support read or write barriers. As a result, these +intrinsics are lowered to normal loads and stores. + +The stack map format generated by this GC strategy can be found in the +:ref:`stackmap-section` using a format documented :ref:`here +`. This format is intended to be the standard +format supported by LLVM going forward. + + +Custom GC Strategies +==================== + +If none of the built in GC strategy descriptions met your needs above, you will +need to define a custom GCStrategy and possibly, a custom LLVM pass to perform +lowering. Your best example of where to start defining a custom GCStrategy +would be to look at one of the built in strategies. + +You may be able to structure this additional code as a loadable plugin library. +Loadable plugins are sufficient if all you need is to enable a different +combination of built in functionality, but if you need to provide a custom +lowering pass, you will need to build a patched version of LLVM. If you think +you need a patched build, please ask for advice on llvm-dev. There may be an +easy way we can extend the support to make it work for your use case without +requiring a custom build. + +Collector Requirements +---------------------- + +You should be able to leverage any existing collector library that includes the following elements: + +#. A memory allocator which exposes an allocation function your compiled + code can call. + +#. A binary format for the stack map. A stack map describes the location + of references at a safepoint and is used by precise collectors to identify + references within a stack frame on the machine stack. Note that collectors + which conservatively scan the stack don't require such a structure. + +#. A stack crawler to discover functions on the call stack, and enumerate the + references listed in the stack map for each call site. + +#. A mechanism for identifying references in global locations (e.g. global + variables). + +#. If you collector requires them, an LLVM IR implementation of your collectors + load and store barriers. Note that since many collectors don't require + barriers at all, LLVM defaults to lowering such barriers to normal loads + and stores unless you arrange otherwise. + + Implementing a collector plugin -=============================== +------------------------------- User code specifies which GC code generation to use with the ``gc`` function attribute or, equivalently, with the ``setGC`` method of ``Function``. @@ -721,8 +833,9 @@ this feature should be used by all GC plugins. It is enabled by default. Custom lowering of intrinsics: ``CustomRoots``, ``CustomReadBarriers``, and ``CustomWriteBarriers`` --------------------------------------------------------------------------------------------------- -For GCs which use barriers or unusual treatment of stack roots, these flags -allow the collector to perform arbitrary transformations of the LLVM IR: +For GCs which use barriers or unusual treatment of stack roots, these +flags allow the collector to perform arbitrary transformations of the +LLVM IR: .. code-block:: c++ @@ -733,70 +846,18 @@ allow the collector to perform arbitrary transformations of the LLVM IR: CustomReadBarriers = true; CustomWriteBarriers = true; } - - virtual bool initializeCustomLowering(Module &M); - virtual bool performCustomLowering(Function &F); }; -If any of these flags are set, then LLVM suppresses its default lowering for the -corresponding intrinsics and instead calls ``performCustomLowering``. - -LLVM's default action for each intrinsic is as follows: - -* ``llvm.gcroot``: Leave it alone. The code generator must see it or the stack - map will not be computed. - -* ``llvm.gcread``: Substitute a ``load`` instruction. - -* ``llvm.gcwrite``: Substitute a ``store`` instruction. - -If ``CustomReadBarriers`` or ``CustomWriteBarriers`` are specified, then -``performCustomLowering`` **must** eliminate the corresponding barriers. +If any of these flags are set, LLVM suppresses its default lowering for +the corresponding intrinsics. Instead, you must provide a custom Pass +which lowers the intrinsics as desired. If you have opted in to custom +lowering of a particular intrinsic your pass **must** eliminate all +instances of the corresponding intrinsic in functions which opt in to +your GC. The best example of such a pass is the ShadowStackGC and it's +ShadowStackGCLowering pass. -``performCustomLowering`` must comply with the same restrictions as -:ref:`FunctionPass::runOnFunction ` -Likewise, ``initializeCustomLowering`` has the same semantics as -:ref:`Pass::doInitialization(Module&) -` - -The following can be used as a template: - -.. code-block:: c++ - - #include "llvm/IR/Module.h" - #include "llvm/IR/IntrinsicInst.h" - - bool MyGC::initializeCustomLowering(Module &M) { - return false; - } - - bool MyGC::performCustomLowering(Function &F) { - bool MadeChange = false; - - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ) - if (IntrinsicInst *CI = dyn_cast(II++)) - if (Function *F = CI->getCalledFunction()) - switch (F->getIntrinsicID()) { - case Intrinsic::gcwrite: - // Handle llvm.gcwrite. - CI->eraseFromParent(); - MadeChange = true; - break; - case Intrinsic::gcread: - // Handle llvm.gcread. - CI->eraseFromParent(); - MadeChange = true; - break; - case Intrinsic::gcroot: - // Handle llvm.gcroot. - CI->eraseFromParent(); - MadeChange = true; - break; - } - - return MadeChange; - } +There is currently no way to register such a custom lowering pass +without building a custom copy of LLVM. .. _safe-points: diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index 316f1f7..fa55ece 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -230,7 +230,7 @@ our build systems: * Clang 3.1 * GCC 4.7 -* Visual Studio 2012 +* Visual Studio 2013 Anything older than these toolchains *may* work, but will require forcing the build system with a special option and is not really a supported host platform. @@ -280,7 +280,7 @@ Getting a Modern Host C++ Toolchain This section mostly applies to Linux and older BSDs. On Mac OS X, you should have a sufficiently modern Xcode, or you will likely need to upgrade until you -do. On Windows, just use Visual Studio 2012 as the host compiler, it is +do. On Windows, just use Visual Studio 2013 as the host compiler, it is explicitly supported and widely available. FreeBSD 10.0 and newer have a modern Clang as the system compiler. diff --git a/docs/GettingStartedVS.rst b/docs/GettingStartedVS.rst index fa20912..63e81f5 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 2012 is fine. The LLVM +Any system that can adequately run Visual Studio 2013 is fine. The LLVM source tree and object files, libraries and executables will consume approximately 3GB. Software -------- -You will need Visual Studio 2012 or higher. +You will need Visual Studio 2013 or higher. You will also need the `CMake `_ build system since it generates the project files you will use to build with. diff --git a/docs/HowToSetUpLLVMStyleRTTI.rst b/docs/HowToSetUpLLVMStyleRTTI.rst index 96275e7..3892994 100644 --- a/docs/HowToSetUpLLVMStyleRTTI.rst +++ b/docs/HowToSetUpLLVMStyleRTTI.rst @@ -40,14 +40,14 @@ RTTI for this class hierarchy: double SideLength; public: Square(double S) : SideLength(S) {} - double computeArea() /* override */; + double computeArea() override; }; class Circle : public Shape { double Radius; public: Circle(double R) : Radius(R) {} - double computeArea() /* override */; + double computeArea() override; }; The most basic working setup for LLVM-style RTTI requires the following @@ -135,7 +135,7 @@ steps: public: - Square(double S) : SideLength(S) {} + Square(double S) : Shape(SK_Square), SideLength(S) {} - double computeArea() /* override */; + double computeArea() override; }; class Circle : public Shape { @@ -143,7 +143,7 @@ steps: public: - Circle(double R) : Radius(R) {} + Circle(double R) : Shape(SK_Circle), Radius(R) {} - double computeArea() /* override */; + double computeArea() override; }; #. Finally, you need to inform LLVM's RTTI templates how to dynamically @@ -175,7 +175,7 @@ steps: double SideLength; public: Square(double S) : Shape(SK_Square), SideLength(S) {} - double computeArea() /* override */; + double computeArea() override; + + static bool classof(const Shape *S) { + return S->getKind() == SK_Square; @@ -186,7 +186,7 @@ steps: double Radius; public: Circle(double R) : Shape(SK_Circle), Radius(R) {} - double computeArea() /* override */; + double computeArea() override; + + static bool classof(const Shape *S) { + return S->getKind() == SK_Circle; @@ -377,6 +377,20 @@ contract for ``classof`` is "return ``true`` if the dynamic type of the argument is-a ``C``". As long as your implementation fulfills this contract, you can tweak and optimize it as much as you want. +For example, LLVM-style RTTI can work fine in the presence of +multiple-inheritance by defining an appropriate ``classof``. +An example of this in practice is +`Decl `_ vs. +`DeclContext `_ +inside Clang. +The ``Decl`` hierarchy is done very similarly to the example setup +demonstrated in this tutorial. +The key part is how to then incorporate ``DeclContext``: all that is needed +is in ``bool DeclContext::classof(const Decl *)``, which asks the question +"Given a ``Decl``, how can I determine if it is-a ``DeclContext``?". +It answers this with a simple switch over the set of ``Decl`` "kinds", and +returning true for ones that are known to be ``DeclContext``'s. + .. TODO:: Touch on some of the more advanced features, like ``isa_impl`` and diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 3b7d80b..a0e9b18 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -75,7 +75,7 @@ identifiers, for different purposes: #. Named values are represented as a string of characters with their prefix. For example, ``%foo``, ``@DivisionByZero``, ``%a.really.long.identifier``. The actual regular expression used is - '``[%@][a-zA-Z$._][a-zA-Z$._0-9]*``'. Identifiers that require other + '``[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*``'. Identifiers that require other characters in their names can be surrounded with quotes. Special characters may be escaped using ``"\xx"`` where ``xx`` is the ASCII code for the character in hexadecimal. In this way, any character can @@ -170,7 +170,7 @@ symbol table entries. Here is an example of the "hello world" module: } ; Named metadata - !0 = metadata !{i32 42, null, metadata !"string"} + !0 = !{i32 42, null, !"string"} !foo = !{!0} This example is made up of a :ref:`global variable ` named @@ -368,7 +368,7 @@ added in the future: The idea behind this convention is to support calls to runtime functions that have a hot path and a cold path. The hot path is usually a small piece - of code that doesn't many registers. The cold path might need to call out to + of code that doesn't use many registers. The cold path might need to call out to another function and therefore only needs to preserve the caller-saved registers, which haven't already been saved by the caller. The `PreserveMost` calling convention is very similar to the `cold` calling @@ -521,7 +521,7 @@ Global Variables Global variables define regions of memory allocated at compilation time instead of run-time. -Global variables definitions must be initialized. +Global variable definitions must be initialized. Global variables in other translation units can also be declared, in which case they don't have an initializer. @@ -588,7 +588,7 @@ iteration. The maximum alignment is ``1 << 29``. Globals can also have a :ref:`DLL storage class `. -Variables and aliasaes can have a +Variables and aliases can have a :ref:`Thread Local Storage Model `. Syntax:: @@ -596,7 +596,8 @@ Syntax:: [@ =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] [AddrSpace] [ExternallyInitialized] [] - [, section "name"] [, align ] + [, section "name"] [, comdat [($name)]] + [, align ] For example, the following defines a global in a numbered address space with an initializer, section, and alignment: @@ -633,7 +634,8 @@ 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:`comdat `, -an optional :ref:`garbage collector name `, an optional :ref:`prefix `, an opening +an optional :ref:`garbage collector name `, an optional :ref:`prefix `, +an optional :ref:`prologue `, an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an @@ -643,7 +645,8 @@ 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, an optional -:ref:`garbage collector name ` and an optional :ref:`prefix `. +:ref:`garbage collector name `, an optional :ref:`prefix `, +and an optional :ref:`prologue `. 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 @@ -663,7 +666,7 @@ predecessors, it also cannot have any :ref:`PHI nodes `. LLVM allows an explicit section to be specified for functions. If the target supports it, it will emit functions to the section specified. -Additionally, the function can placed in a COMDAT. +Additionally, the function can be placed in a COMDAT. An explicit alignment may be specified for a function. If not present, or if the alignment is set to zero, the alignment of the function is set @@ -671,7 +674,7 @@ by the target to whatever it feels convenient. If an explicit alignment is specified, the function is forced to have at least that much alignment. All alignments must be a power of 2. -If the ``unnamed_addr`` attribute is given, the address is know to not +If the ``unnamed_addr`` attribute is given, the address is known to not be significant and two identical functions can be merged. Syntax:: @@ -679,8 +682,8 @@ Syntax:: define [linkage] [visibility] [DLLStorageClass] [cconv] [ret attrs] @ ([argument list]) - [unnamed_addr] [fn Attrs] [section "name"] [comdat $] - [align N] [gc] [prefix Constant] { ... } + [unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]] + [align N] [gc] [prefix Constant] [prologue Constant] { ... } The argument list is a comma seperated sequence of arguments where each argument is of the following form @@ -713,7 +716,7 @@ The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``, ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers might not correctly handle dropping a weak symbol that is aliased. -Alias that are not ``unnamed_addr`` are guaranteed to have the same address as +Aliases that are not ``unnamed_addr`` are guaranteed to have the same address as the aliasee expression. ``unnamed_addr`` ones are only guaranteed to point to the same content. @@ -773,12 +776,21 @@ the COMDAT key's section is the largest: .. code-block:: llvm $foo = comdat largest - @foo = global i32 2, comdat $foo + @foo = global i32 2, comdat($foo) - define void @bar() comdat $foo { + define void @bar() comdat($foo) { ret void } +As a syntactic sugar the ``$name`` can be omitted if the name is the same as +the global name: + +.. code-block:: llvm + + $foo = comdat any + @foo = global i32 2, comdat + + In a COFF object file, this will create a COMDAT section with selection kind ``IMAGE_COMDAT_SELECT_LARGEST`` containing the contents of the ``@foo`` symbol and another COMDAT section with selection kind @@ -801,8 +813,8 @@ For example: $foo = comdat any $bar = comdat any - @g1 = global i32 42, section "sec", comdat $foo - @g2 = global i32 42, section "sec", comdat $bar + @g1 = global i32 42, section "sec", comdat($foo) + @g2 = global i32 42, section "sec", comdat($bar) From the object file perspective, this requires the creation of two sections with the same name. This is necessary because both globals belong to different @@ -825,9 +837,9 @@ operands for a named metadata. Syntax:: ; Some unnamed metadata nodes, which are referenced by the named metadata. - !0 = metadata !{metadata !"zero"} - !1 = metadata !{metadata !"one"} - !2 = metadata !{metadata !"two"} + !0 = !{!"zero"} + !1 = !{!"one"} + !2 = !{!"two"} ; A named metadata. !name = !{!0, !1, !2} @@ -941,23 +953,26 @@ Currently, only the following parameter attributes are defined: .. _noalias: ``noalias`` - This indicates that pointer values :ref:`based ` on - the argument or return value do not alias pointer values that are - not *based* on it, ignoring certain "irrelevant" dependencies. For a - call to the parent function, dependencies between memory references - from before or after the call and from those during the call are - "irrelevant" to the ``noalias`` keyword for the arguments and return - value used in that call. The caller shares the responsibility with - the callee for ensuring that these requirements are met. For further - details, please see the discussion of the NoAlias response in :ref:`alias - analysis `. + This indicates that objects accessed via pointer values + :ref:`based ` on the argument or return value are not also + accessed, during the execution of the function, via pointer values not + *based* on the argument or return value. The attribute on a return value + also has additional semantics described below. The caller shares the + responsibility with the callee for ensuring that these requirements are met. + For further details, please see the discussion of the NoAlias response in + :ref:`alias analysis `. Note that this definition of ``noalias`` is intentionally similar - to the definition of ``restrict`` in C99 for function arguments, - though it is slightly weaker. + to the definition of ``restrict`` in C99 for function arguments. For function return values, C99's ``restrict`` is not meaningful, - while LLVM's ``noalias`` is. + while LLVM's ``noalias`` is. Furthermore, the semantics of the ``noalias`` + attribute on return values are stronger than the semantics of the attribute + when used on function arguments. On function return values, the ``noalias`` + attribute indicates that the function acts like a system memory allocation + function, returning a pointer to allocated storage disjoint from the + storage for any other object accessible to the caller. + ``nocapture`` This indicates that the callee does not make any copies of the pointer that outlive the callee itself. This is not a valid @@ -999,66 +1014,101 @@ Currently, only the following parameter attributes are defined: .. _gc: -Garbage Collector Names ------------------------ +Garbage Collector Strategy Names +-------------------------------- -Each function may specify a garbage collector name, which is simply a +Each function may specify a garbage collector strategy name, which is simply a string: .. code-block:: llvm define void @f() gc "name" { ... } -The compiler declares the supported values of *name*. Specifying a -collector will cause the compiler to alter its output in order to -support the named garbage collection algorithm. +The supported values of *name* includes those :ref:`built in to LLVM +` and any provided by loaded plugins. Specifying a GC +strategy will cause the compiler to alter its output in order to support the +named garbage collection algorithm. Note that LLVM itself does not contain a +garbage collector, this functionality is restricted to generating machine code +which can interoperate with a collector provided externally. .. _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. +Prefix data is data associated with a function which the code +generator will emit immediately before the function's entrypoint. +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 and dereference +index -1. This implies that the IR symbol points just past the end of +the prefix data. For instance, take the example of a function annotated +with a single ``i32``, + +.. code-block:: llvm + + define void @f() prefix i32 123 { ... } + +The prefix data can be referenced as, + +.. code-block:: llvm + + %0 = bitcast *void () @f to *i32 + %a = getelementptr inbounds *i32 %0, i32 -1 + %b = load i32* %a + +Prefix data is laid out as if it were an initializer for a global variable +of the prefix data's type. The function will be placed such that the +beginning of the prefix data is aligned. This means that if the size +of the prefix data is not a multiple of the alignment size, the +function's entrypoint will not be aligned. If alignment of the +function's entrypoint is desired, padding must be added to the prefix +data. + +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. + +.. _prologuedata: -To maintain the semantics of ordinary function calls, the prefix data must +Prologue Data +------------- + +The ``prologue`` attribute allows arbitrary code (encoded as bytes) to +be inserted prior to the function body. This can be used for enabling +function hot-patching and instrumentation. + +To maintain the semantics of ordinary function calls, the prologue 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 prologue 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. +definition without needing to reason about the prologue data. Obviously this +makes the format of the prologue 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``, +A trivial example of valid prologue data for the x86 architecture is ``i8 144``, which encodes the ``nop`` instruction: .. code-block:: llvm - define void @f() prefix i8 144 { ... } + define void @f() prologue 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 +Generally prologue data can be formed by encoding a relative branch instruction +which skips the metadata, as in this example of valid prologue 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}> { ... } + define void @f() prologue %0 <{ i8 235, i8 8, i8* @md}> { ... } -A function may have prefix data but no body. This has similar semantics +A function may have prologue 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. @@ -1189,9 +1239,12 @@ example: normally. This produces undefined behavior at runtime if the function ever does dynamically return. ``nounwind`` - This function attribute indicates that the function never returns - with an unwind or exceptional control flow. If the function does - unwind, its runtime behavior is undefined. + This function attribute indicates that the function never raises an + exception. If the function does raise an exception, its runtime + behavior is undefined. However, functions marked nounwind may still + trap or generate asynchronous exceptions. Exception handling schemes + that are recognized by LLVM to handle asynchronous exceptions, such + as SEH, will still provide their implementation defined semantics. ``optnone`` This function attribute indicates that the function is not optimized by any optimization or code generator passes with the @@ -1732,7 +1785,7 @@ Fast-Math Flags LLVM IR floating-point binary ops (:ref:`fadd `, :ref:`fsub `, :ref:`fmul `, :ref:`fdiv `, -:ref:`frem `) have the following flags that can set to enable +:ref:`frem `) have the following flags that can be set to enable otherwise unsafe floating point operations ``nnan`` @@ -2293,11 +2346,11 @@ constants and smaller complex constants. having to print large zero initializers (e.g. for large arrays) and is always exactly equivalent to using explicit zero initializers. **Metadata node** - A metadata node is a structure-like constant with :ref:`metadata - type `. For example: - "``metadata !{ i32 0, metadata !"test" }``". Unlike other - constants that are meant to be interpreted as part of the - instruction stream, metadata is a place to attach additional + A metadata node is a constant tuple without types. For example: + "``!{!0, !{!2, !0}, !"test"}``". Metadata can reference constant values, + for example: "``!{!0, i32 0, i8* @global, i64 (i64)* @function, !"str"}``". + Unlike other typed constants that are meant to be interpreted as part of + the instruction stream, metadata is a place to attach additional information such as debug info. Global Variable and Function Addresses @@ -2771,15 +2824,21 @@ occurs on. .. _metadata: -Metadata Nodes and Metadata Strings ------------------------------------ +Metadata +======== LLVM IR allows metadata to be attached to instructions in the program that can convey extra information about the code to the optimizers and code generator. One example application of metadata is source-level debug information. There are two metadata primitives: strings and nodes. -All metadata has the ``metadata`` type and is identified in syntax by a -preceding exclamation point ('``!``'). + +Metadata does not have a type, and is not a value. If referenced from a +``call`` instruction, it uses the ``metadata`` type. + +All metadata are identified in syntax by a exclamation point ('``!``'). + +Metadata Nodes and Metadata Strings +----------------------------------- A metadata string is a string surrounded by double quotes. It can contain any character by escaping non-printable characters with @@ -2793,7 +2852,17 @@ their operand. For example: .. code-block:: llvm - !{ metadata !"test\00", i32 10} + !{ !"test\00", i32 10} + +Metadata nodes that aren't uniqued use the ``distinct`` keyword. For example: + +.. code-block:: llvm + + !0 = distinct !{!"test\00", i32 10} + +``distinct`` nodes are useful when nodes shouldn't be merged based on their +content. They can also occur when transformations cause uniquing collisions +when metadata operands change. A :ref:`named metadata ` is a collection of metadata nodes, which can be looked up in the module symbol table. For @@ -2801,7 +2870,7 @@ example: .. code-block:: llvm - !foo = metadata !{!4, !3} + !foo = !{!4, !3} Metadata can be used as function arguments. Here ``llvm.dbg.value`` function is using two metadata arguments: @@ -2820,6 +2889,23 @@ attached to the ``add`` instruction using the ``!dbg`` identifier: More information about specific metadata nodes recognized by the optimizers and code generator is found below. +Specialized Metadata Nodes +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Specialized metadata nodes are custom data structures in metadata (as opposed +to generic tuples). Their fields are labelled, and can be specified in any +order. + +MDLocation +"""""""""" + +``MDLocation`` nodes represent source debug locations. The ``scope:`` field is +mandatory. + +.. code-block:: llvm + + !0 = !MDLocation(line: 2900, column: 42, scope: !1, inlinedAt: !2) + '``tbaa``' Metadata ^^^^^^^^^^^^^^^^^^^ @@ -2834,10 +2920,10 @@ to three fields, e.g.: .. code-block:: llvm - !0 = metadata !{ metadata !"an example type tree" } - !1 = metadata !{ metadata !"int", metadata !0 } - !2 = metadata !{ metadata !"float", metadata !0 } - !3 = metadata !{ metadata !"const float", metadata !2, i64 1 } + !0 = !{ !"an example type tree" } + !1 = !{ !"int", !0 } + !2 = !{ !"float", !0 } + !3 = !{ !"const float", !2, i64 1 } The first field is an identity field. It can be any value, usually a metadata string, which uniquely identifies the type. The most important @@ -2877,7 +2963,7 @@ its tbaa tag. e.g.: .. code-block:: llvm - !4 = metadata !{ i64 0, i64 4, metadata !1, i64 8, i64 4, metadata !2 } + !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 } This describes a struct with two fields. The first is at offset 0 bytes with size 4 bytes, and has tbaa tag !1. The second is at offset 8 bytes @@ -2898,7 +2984,7 @@ collection of memory access instructions that carry ``alias.scope`` metadata. Each type of metadata specifies a list of scopes where each scope has an id and a domain. When evaluating an aliasing query, if for some some domain, the set of scopes with that domain in one instruction's ``alias.scope`` list is a -subset of (or qual to) the set of scopes for that domain in another +subset of (or equal to) the set of scopes for that domain in another instruction's ``noalias`` list, then the two memory accesses are assumed not to alias. @@ -2920,18 +3006,18 @@ For example, .. code-block:: llvm ; Two scope domains: - !0 = metadata !{metadata !0} - !1 = metadata !{metadata !1} + !0 = !{!0} + !1 = !{!1} ; Some scopes in these domains: - !2 = metadata !{metadata !2, metadata !0} - !3 = metadata !{metadata !3, metadata !0} - !4 = metadata !{metadata !4, metadata !1} + !2 = !{!2, !0} + !3 = !{!3, !0} + !4 = !{!4, !1} ; Some scope lists: - !5 = metadata !{metadata !4} ; A list containing only scope !4 - !6 = metadata !{metadata !4, metadata !3, metadata !2} - !7 = metadata !{metadata !3} + !5 = !{!4} ; A list containing only scope !4 + !6 = !{!4, !3, !2} + !7 = !{!3} ; These two instructions don't alias: %0 = load float* %c, align 4, !alias.scope !5 @@ -2968,7 +3054,7 @@ number representing the maximum relative error, for example: .. code-block:: llvm - !0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs + !0 = !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs '``range``' Metadata ^^^^^^^^^^^^^^^^^^^^ @@ -3000,10 +3086,10 @@ Examples: %d = invoke i8 @bar() to label %cont unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5 ... - !0 = metadata !{ i8 0, i8 2 } - !1 = metadata !{ i8 255, i8 2 } - !2 = metadata !{ i8 0, i8 2, i8 3, i8 6 } - !3 = metadata !{ i8 -2, i8 0, i8 3, i8 6 } + !0 = !{ i8 0, i8 2 } + !1 = !{ i8 255, i8 2 } + !2 = !{ i8 0, i8 2, i8 3, i8 6 } + !3 = !{ i8 -2, i8 0, i8 3, i8 6 } '``llvm.loop``' ^^^^^^^^^^^^^^^ @@ -3023,8 +3109,8 @@ constructs: .. code-block:: llvm - !0 = metadata !{ metadata !0 } - !1 = metadata !{ metadata !1 } + !0 = !{!0} + !1 = !{!1} The loop identifier metadata can be used to specify additional per-loop metadata. Any operands after the first operand can be treated @@ -3035,8 +3121,8 @@ suggests an unroll factor to the loop unroller: br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0 ... - !0 = metadata !{ metadata !0, metadata !1 } - !1 = metadata !{ metadata !"llvm.loop.unroll.count", i32 4 } + !0 = !{!0, !1} + !1 = !{!"llvm.loop.unroll.count", i32 4} '``llvm.loop.vectorize``' and '``llvm.loop.interleave``' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3061,7 +3147,7 @@ example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.interleave.count", i32 4 } + !0 = !{!"llvm.loop.interleave.count", i32 4} Note that setting ``llvm.loop.interleave.count`` to 1 disables interleaving multiple iterations of the loop. If ``llvm.loop.interleave.count`` is set to 0 @@ -3077,8 +3163,8 @@ is a bit. If the bit operand value is 1 vectorization is enabled. A value of .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.vectorize.enable", i1 0 } - !1 = metadata !{ metadata !"llvm.loop.vectorize.enable", i1 1 } + !0 = !{!"llvm.loop.vectorize.enable", i1 0} + !1 = !{!"llvm.loop.vectorize.enable", i1 1} '``llvm.loop.vectorize.width``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3089,7 +3175,7 @@ operand is an integer specifying the width. For example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.vectorize.width", i32 4 } + !0 = !{!"llvm.loop.vectorize.width", i32 4} Note that setting ``llvm.loop.vectorize.width`` to 1 disables vectorization of the loop. If ``llvm.loop.vectorize.width`` is set to @@ -3116,7 +3202,7 @@ example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.unroll.count", i32 4 } + !0 = !{!"llvm.loop.unroll.count", i32 4} If the trip count of the loop is less than the unroll count the loop will be partially unrolled. @@ -3129,7 +3215,7 @@ which is the string ``llvm.loop.unroll.disable``. For example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.unroll.disable" } + !0 = !{!"llvm.loop.unroll.disable"} '``llvm.loop.unroll.full``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3140,7 +3226,7 @@ For example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.unroll.full" } + !0 = !{!"llvm.loop.unroll.full"} '``llvm.mem``' ^^^^^^^^^^^^^^^ @@ -3191,7 +3277,7 @@ metadata types that refer to the same loop identifier metadata. for.end: ... - !0 = metadata !{ metadata !0 } + !0 = !{!0} It is also possible to have nested parallel loops. In that case the memory accesses refer to a list of loop identifier metadata nodes instead of @@ -3221,9 +3307,15 @@ the loop identifier metadata node directly: outer.for.end: ; preds = %for.body ... - !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 + !0 = !{!1, !2} ; a list of loop identifiers + !1 = !{!1} ; an identifier for the inner loop + !2 = !{!2} ; an identifier for the outer loop + +'``llvm.bitsets``' +^^^^^^^^^^^^^^^^^^ + +The ``llvm.bitsets`` global metadata is used to implement +:doc:`bitsets `. Module Flags Metadata ===================== @@ -3307,12 +3399,12 @@ An example of module flags: .. code-block:: llvm - !0 = metadata !{ i32 1, metadata !"foo", i32 1 } - !1 = metadata !{ i32 4, metadata !"bar", i32 37 } - !2 = metadata !{ i32 2, metadata !"qux", i32 42 } - !3 = metadata !{ i32 3, metadata !"qux", - metadata !{ - metadata !"foo", i32 1 + !0 = !{ i32 1, !"foo", i32 1 } + !1 = !{ i32 4, !"bar", i32 37 } + !2 = !{ i32 2, !"qux", i32 42 } + !3 = !{ i32 3, !"qux", + !{ + !"foo", i32 1 } } !llvm.module.flags = !{ !0, !1, !2, !3 } @@ -3333,7 +3425,7 @@ An example of module flags: :: - metadata !{ metadata !"foo", i32 1 } + !{ !"foo", i32 1 } The behavior is to emit an error if the ``llvm.module.flags`` does not contain a flag with the ID ``!"foo"`` that has the value '1' after linking is @@ -3409,10 +3501,10 @@ For example, the following metadata section specifies two separate sets of linker options, presumably to link against ``libz`` and the ``Cocoa`` framework:: - !0 = metadata !{ i32 6, metadata !"Linker Options", - metadata !{ - metadata !{ metadata !"-lz" }, - metadata !{ metadata !"-framework", metadata !"Cocoa" } } } + !0 = !{ i32 6, !"Linker Options", + !{ + !{ !"-lz" }, + !{ !"-framework", !"Cocoa" } } } !llvm.module.flags = !{ !0 } The metadata encoding as lists of lists of options, as opposed to a collapsed @@ -3458,8 +3550,8 @@ compiled with a ``wchar_t`` width of 4 bytes, and the underlying type of an enum is the smallest type which can represent all of its values:: !llvm.module.flags = !{!0, !1} - !0 = metadata !{i32 1, metadata !"short_wchar", i32 1} - !1 = metadata !{i32 1, metadata !"short_enum", i32 0} + !0 = !{i32 1, !"short_wchar", i32 1} + !1 = !{i32 1, !"short_enum", i32 0} .. _intrinsicglobalvariables: @@ -5208,10 +5300,11 @@ as the ``MOVNT`` instruction on x86. The optional ``!invariant.load`` metadata must reference a single 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 -hoisting it out of loops using loop invariant code motion. +instruction tells the optimizer and code generator that the address +operand to this load points to memory which can be assumed unchanged. +Being invariant does not imply that a location is dereferenceable, +but it does imply that once the location is known dereferenceable +its value is henceforth unchanging. The optional ``!nonnull`` metadata must reference a single metadata name ```` corresponding to a metadata node with no @@ -7016,18 +7109,28 @@ arbitrarily complex and require, for example, memory allocation. Accurate Garbage Collection Intrinsics -------------------------------------- -LLVM support for `Accurate Garbage Collection `_ -(GC) requires the implementation and generation of these intrinsics. +LLVM's support for `Accurate Garbage Collection `_ +(GC) requires the frontend to generate code containing appropriate intrinsic +calls and select an appropriate GC strategy which knows how to lower these +intrinsics in a manner which is appropriate for the target collector. + These intrinsics allow identification of :ref:`GC roots on the stack `, as well as garbage collector implementations that require :ref:`read ` and :ref:`write ` barriers. -Front-ends for type-safe garbage collected languages should generate +Frontends for type-safe garbage collected languages should generate these intrinsics to make use of the LLVM garbage collectors. For more -details, see `Accurate Garbage Collection with -LLVM `_. +details, see `Garbage Collection with LLVM `_. -The garbage collection intrinsics only operate on objects in the generic -address space (address space zero). +Experimental Statepoint Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +LLVM provides an second experimental set of intrinsics for describing garbage +collection safepoints in compiled code. These intrinsics are an alternative +to the ``llvm.gcroot`` intrinsics, but are compatible with the ones for +:ref:`read ` and :ref:`write ` barriers. The +differences in approach are covered in the `Garbage Collection with LLVM +`_ documentation. The intrinsics themselves are +described in :doc:`Statepoints`. .. _int_gcroot: @@ -7217,6 +7320,56 @@ Note that calling this intrinsic does not prevent function inlining or other aggressive transformations, so the value returned may not be that of the obvious source-language caller. +'``llvm.frameallocate``' and '``llvm.framerecover``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.frameallocate(i32 %size) + declare i8* @llvm.framerecover(i8* %func, i8* %fp) + +Overview: +""""""""" + +The '``llvm.frameallocate``' intrinsic allocates stack memory at some fixed +offset from the frame pointer, and the '``llvm.framerecover``' +intrinsic applies that offset to a live frame pointer to recover the address of +the allocation. The offset is computed during frame layout of the caller of +``llvm.frameallocate``. + +Arguments: +"""""""""" + +The ``size`` argument to '``llvm.frameallocate``' must be a constant integer +indicating the amount of stack memory to allocate. As with allocas, allocating +zero bytes is legal, but the result is undefined. + +The ``func`` argument to '``llvm.framerecover``' must be a constant +bitcasted pointer to a function defined in the current module. The code +generator cannot determine the frame allocation offset of functions defined in +other modules. + +The ``fp`` argument to '``llvm.framerecover``' must be a frame +pointer of a call frame that is currently live. The return value of +'``llvm.frameaddress``' is one way to produce such a value, but most platforms +also expose the frame pointer through stack unwinding mechanisms. + +Semantics: +"""""""""" + +These intrinsics allow a group of functions to access one stack memory +allocation in an ancestor stack frame. The memory returned from +'``llvm.frameallocate``' may be allocated prior to stack realignment, so the +memory is only aligned to the ABI-required stack alignment. Each function may +only call '``llvm.frameallocate``' one or zero times from the function entry +block. The frame allocation intrinsic inhibits inlining, as any frame +allocations in the inlined function frame are likely to be at a different +offset from the one used by '``llvm.framerecover``' called with the +uninlined function. + .. _int_read_register: .. _int_write_register: @@ -7232,7 +7385,7 @@ Syntax: declare i64 @llvm.read_register.i64(metadata) declare void @llvm.write_register.i32(metadata, i32 @value) declare void @llvm.write_register.i64(metadata, i64 @value) - !0 = metadata !{metadata !"sp\00"} + !0 = !{!"sp\00"} Overview: """"""""" @@ -7454,6 +7607,50 @@ time library. This instrinsic does *not* empty the instruction pipeline. Modifications of the current function are outside the scope of the intrinsic. +'``llvm.instrprof_increment``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.instrprof_increment(i8* , i64 , + i32 , i32 ) + +Overview: +""""""""" + +The '``llvm.instrprof_increment``' intrinsic can be emitted by a +frontend for use with instrumentation based profiling. These will be +lowered by the ``-instrprof`` pass to generate execution counts of a +program at runtime. + +Arguments: +"""""""""" + +The first argument is a pointer to a global variable containing the +name of the entity being instrumented. This should generally be the +(mangled) function name for a set of counters. + +The second argument is a hash value that can be used by the consumer +of the profile data to detect changes to the instrumented source, and +the third is the number of counters associated with ``name``. It is an +error if ``hash`` or ``num-counters`` differ between two instances of +``instrprof_increment`` that refer to the same name. + +The last argument refers to which of the counters for ``name`` should +be incremented. It should be a value between 0 and ``num-counters``. + +Semantics: +"""""""""" + +This intrinsic represents an increment of a profiling counter. It will +cause the ``-instrprof`` pass to generate the appropriate data +structures and the code to increment the appropriate value, in a +format that can be written out by a compiler runtime and consumed via +the ``llvm-profdata`` tool. + Standard C Library Intrinsics ----------------------------- @@ -8499,7 +8696,7 @@ Arguments: """""""""" The first argument is the value to be counted. This argument may be of -any integer type, or a vectory with integer element type. The return +any integer type, or a vector with integer element type. The return type must match the first argument type. The second argument must be a constant and is a flag to indicate whether @@ -8546,7 +8743,7 @@ Arguments: """""""""" The first argument is the value to be counted. This argument may be of -any integer type, or a vectory with integer element type. The return +any integer type, or a vector with integer element type. The return type must match the first argument type. The second argument must be a constant and is a flag to indicate whether @@ -9142,6 +9339,93 @@ intrinsic returns the executable address corresponding to ``tramp`` after performing the required machine specific adjustments. The pointer returned can then be :ref:`bitcast and executed `. +Masked Vector Load and Store Intrinsics +--------------------------------------- + +LLVM provides intrinsics for predicated vector load and store operations. The predicate is specified by a mask operand, which holds one bit per vector element, switching the associated vector lane on or off. The memory addresses corresponding to the "off" lanes are not accessed. When all bits of the mask are on, the intrinsic is identical to a regular vector load or store. When all bits are off, no memory is accessed. + +.. _int_mload: + +'``llvm.masked.load.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The loaded data is a vector of any integer or floating point data type. + +:: + + declare <16 x float> @llvm.masked.load.v16f32 (<16 x float>* , i32 , <16 x i1> , <16 x float> ) + declare <2 x double> @llvm.masked.load.v2f64 (<2 x double>* , i32 , <2 x i1> , <2 x double> ) + +Overview: +""""""""" + +Reads a vector from memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. The masked-off lanes in the result vector are taken from the corresponding lanes in the passthru operand. + + +Arguments: +"""""""""" + +The first operand is the base pointer for the load. The second operand is the alignment of the source location. It must be a constant integer value. The third operand, mask, is a vector of boolean 'i1' values with the same number of elements as the return type. The fourth is a pass-through value that is used to fill the masked-off lanes of the result. The return type, underlying type of the base pointer and the type of passthru operand are the same vector types. + + +Semantics: +"""""""""" + +The '``llvm.masked.load``' intrinsic is designed for conditional reading of selected vector elements in a single IR operation. It is useful for targets that support vector masked loads and allows vectorizing predicated basic blocks on these targets. Other targets may support this intrinsic differently, for example by lowering it into a sequence of branches that guard scalar load operations. +The result of this operation is equivalent to a regular vector load instruction followed by a 'select' between the loaded and the passthru values, predicated on the same mask. However, using this intrinsic prevents exceptions on memory access to masked-off lanes. + + +:: + + %res = call <16 x float> @llvm.masked.load.v16f32 (<16 x float>* %ptr, i32 4, <16 x i1>%mask, <16 x float> %passthru) + + ;; The result of the two following instructions is identical aside from potential memory access exception + %loadlal = load <16 x float>* %ptr, align 4 + %res = select <16 x i1> %mask, <16 x float> %loadlal, <16 x float> %passthru + +.. _int_mstore: + +'``llvm.masked.store.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The data stored in memory is a vector of any integer or floating point data type. + +:: + + declare void @llvm.masked.store.v8i32 (<8 x i32> , <8 x i32> * , i32 , <8 x i1> ) + declare void @llvm.masked.store.v16f32(<16 x i32> , <16 x i32>* , i32 , <16 x i1> ) + +Overview: +""""""""" + +Writes a vector to memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. + +Arguments: +"""""""""" + +The first operand is the vector value to be written to memory. The second operand is the base pointer for the store, it has the same underlying type as the value operand. The third operand is the alignment of the destination location. The fourth operand, mask, is a vector of boolean values. The types of the mask and the value operand must have the same number of vector elements. + + +Semantics: +"""""""""" + +The '``llvm.masked.store``' intrinsics is designed for conditional writing of selected vector elements in a single IR operation. It is useful for targets that support vector masked store and allows vectorizing predicated basic blocks on these targets. Other targets may support this intrinsic differently, for example by lowering it into a sequence of branches that guard scalar store operations. +The result of this operation is equivalent to a load-modify-store sequence. However, using this intrinsic prevents exceptions and data races on memory access to masked-off lanes. + +:: + + call void @llvm.masked.store.v16f32(<16 x float> %value, <16 x float>* %ptr, i32 4, <16 x i1> %mask) + + ;; The result of the following instructions is identical aside from potential data races and memory access exceptions + %oldval = load <16 x float>* %ptr, align 4 + %res = select <16 x i1> %mask, <16 x float> %value, <16 x float> %oldval + store <16 x float> %res, <16 x float>* %ptr, align 4 + + Memory Use Markers ------------------ @@ -9617,15 +9901,40 @@ generated for this intrinsic, and instructions that contribute only to the provided condition are not used for code generation. If the condition is violated during execution, the behavior is undefined. -Please note that optimizer might limit the transformations performed on values +Note that the optimizer might limit the transformations performed on values used by the ``llvm.assume`` intrinsic in order to preserve the instructions only used to form the intrinsic's input argument. This might prove undesirable -if the extra information provided by the ``llvm.assume`` intrinsic does cause +if the extra information provided by the ``llvm.assume`` intrinsic does not cause sufficient overall improvement in code quality. For this reason, ``llvm.assume`` should not be used to document basic mathematical invariants that the optimizer can otherwise deduce or facts that are of little use to the optimizer. +.. _bitset.test: + +'``llvm.bitset.test``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i1 @llvm.bitset.test(i8* %ptr, metadata %bitset) nounwind readnone + + +Arguments: +"""""""""" + +The first argument is a pointer to be tested. The second argument is a +metadata string containing the name of a :doc:`bitset `. + +Overview: +""""""""" + +The ``llvm.bitset.test`` intrinsic tests whether the given pointer is a +member of the given bitset. + '``llvm.donothing``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/LinkTimeOptimization.rst b/docs/LinkTimeOptimization.rst index c15abd3..55a7486 100644 --- a/docs/LinkTimeOptimization.rst +++ b/docs/LinkTimeOptimization.rst @@ -134,7 +134,7 @@ Alternative Approaches Multi-phase communication between ``libLTO`` and linker ======================================================= -The linker collects information about symbol defininitions and uses in various +The linker collects information about symbol definitions and uses in various link objects which is more accurate than any information collected by other tools during typical build cycles. The linker collects this information by looking at the definitions and uses of symbols in native .o files and using diff --git a/docs/MergeFunctions.rst b/docs/MergeFunctions.rst new file mode 100644 index 0000000..6b8012e --- /dev/null +++ b/docs/MergeFunctions.rst @@ -0,0 +1,802 @@ +================================= +MergeFunctions pass, how it works +================================= + +.. contents:: + :local: + +Introduction +============ +Sometimes code contains equal functions, or functions that does exactly the same +thing even though they are non-equal on the IR level (e.g.: multiplication on 2 +and 'shl 1'). It could happen due to several reasons: mainly, the usage of +templates and automatic code generators. Though, sometimes user itself could +write the same thing twice :-) + +The main purpose of this pass is to recognize such functions and merge them. + +Why would I want to read this document? +--------------------------------------- +Document is the extension to pass comments and describes the pass logic. It +describes algorithm that is used in order to compare functions, it also +explains how we could combine equal functions correctly, keeping module valid. + +Material is brought in top-down form, so reader could start learn pass from +ideas and end up with low-level algorithm details, thus preparing him for +reading the sources. + +So main goal is do describe algorithm and logic here; the concept. This document +is good for you, if you *don't want* to read the source code, but want to +understand pass algorithms. Author tried not to repeat the source-code and +cover only common cases, and thus avoid cases when after minor code changes we +need to update this document. + + +What should I know to be able to follow along with this document? +----------------------------------------------------------------- + +Reader should be familiar with common compile-engineering principles and LLVM +code fundamentals. In this article we suppose reader is familiar with +`Single Static Assingment `_ +concepts. Understanding of +`IR structure `_ is +also important. + +We will use such terms as +"`module `_", +"`function `_", +"`basic block `_", +"`user `_", +"`value `_", +"`instruction `_". + +As a good start point, Kaleidoscope tutorial could be used: + +:doc:`tutorial/index` + +Especially it's important to understand chapter 3 of tutorial: + +:doc:`tutorial/LangImpl3` + +Reader also should know how passes work in LLVM, he could use next article as a +reference and start point here: + +:doc:`WritingAnLLVMPass` + +What else? Well perhaps reader also should have some experience in LLVM pass +debugging and bug-fixing. + +What I gain by reading this document? +------------------------------------- +Main purpose is to provide reader with comfortable form of algorithms +description, namely the human reading text. Since it could be hard to +understand algorithm straight from the source code: pass uses some principles +that have to be explained first. + +Author wishes to everybody to avoid case, when you read code from top to bottom +again and again, and yet you don't understand why we implemented it that way. + +We hope that after this article reader could easily debug and improve +MergeFunctions pass and thus help LLVM project. + +Narrative structure +------------------- +Article consists of three parts. First part explains pass functionality on the +top-level. Second part describes the comparison procedure itself. The third +part describes the merging process. + +In every part author also tried to put the contents into the top-down form. +First, the top-level methods will be described, while the terminal ones will be +at the end, in the tail of each part. If reader will see the reference to the +method that wasn't described yet, he will find its description a bit below. + +Basics +====== + +How to do it? +------------- +Do we need to merge functions? Obvious thing is: yes that's a quite possible +case, since usually we *do* have duplicates. And it would be good to get rid of +them. But how to detect such a duplicates? The idea is next: we split functions +onto small bricks (parts), then we compare "bricks" amount, and if it equal, +compare "bricks" themselves, and then do our conclusions about functions +themselves. + +What the difference it could be? For example, on machine with 64-bit pointers +(let's assume we have only one address space), one function stores 64-bit +integer, while another one stores a pointer. So if the target is a machine +mentioned above, and if functions are identical, except the parameter type (we +could consider it as a part of function type), then we can treat ``uint64_t`` +and``void*`` as equal. + +It was just an example; possible details are described a bit below. + +As another example reader may imagine two more functions. First function +performs multiplication on 2, while the second one performs arithmetic right +shift on 1. + +Possible solutions +^^^^^^^^^^^^^^^^^^ +Let's briefly consider possible options about how and what we have to implement +in order to create full-featured functions merging, and also what it would +meant for us. + +Equal functions detection, obviously supposes "detector" method to be +implemented, latter should answer the question "whether functions are equal". +This "detector" method consists of tiny "sub-detectors", each of them answers +exactly the same question, but for function parts. + +As the second step, we should merge equal functions. So it should be a "merger" +method. "Merger" accepts two functions *F1* and *F2*, and produces *F1F2* +function, the result of merging. + +Having such a routines in our hands, we can process whole module, and merge all +equal functions. + +In this case, we have to compare every function with every another function. As +reader could notice, this way seems to be quite expensive. Of course we could +introduce hashing and other helpers, but it is still just an optimization, and +thus the level of O(N*N) complexity. + +Can we reach another level? Could we introduce logarithmical search, or random +access lookup? The answer is: "yes". + +Random-access +""""""""""""" +How it could be done? Just convert each function to number, and gather all of +them in special hash-table. Functions with equal hash are equal. Good hashing +means, that every function part must be taken into account. That means we have +to convert every function part into some number, and then add it into hash. +Lookup-up time would be small, but such approach adds some delay due to hashing +routine. + +Logarithmical search +"""""""""""""""""""" +We could introduce total ordering among the functions set, once we had it we +could then implement a logarithmical search. Lookup time still depends on N, +but adds a little of delay (*log(N)*). + +Present state +""""""""""""" +Both of approaches (random-access and logarithmical) has been implemented and +tested. And both of them gave a very good improvement. And what was most +surprising, logarithmical search was faster; sometimes up to 15%. Hashing needs +some extra CPU time, and it is the main reason why it works slower; in most of +cases total "hashing" time was greater than total "logarithmical-search" time. + +So, preference has been granted to the "logarithmical search". + +Though in the case of need, *logarithmical-search* (read "total-ordering") could +be used as a milestone on our way to the *random-access* implementation. + +Every comparison is based either on the numbers or on flags comparison. In +*random-access* approach we could use the same comparison algorithm. During +comparison we exit once we find the difference, but here we might have to scan +whole function body every time (note, it could be slower). Like in +"total-ordering", we will track every numbers and flags, but instead of +comparison, we should get numbers sequence and then create the hash number. So, +once again, *total-ordering* could be considered as a milestone for even faster +(in theory) random-access approach. + +MergeFunctions, main fields and runOnModule +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +There are two most important fields in class: + +``FnTree`` – the set of all unique functions. It keeps items that couldn't be +merged with each other. It is defined as: + +``std::set FnTree;`` + +Here ``FunctionNode`` is a wrapper for ``llvm::Function`` class, with +implemented “<†operator among the functions set (below we explain how it works +exactly; this is a key point in fast functions comparison). + +``Deferred`` – merging process can affect bodies of functions that are in +``FnTree`` already. Obviously such functions should be rechecked again. In this +case we remove them from ``FnTree``, and mark them as to be rescanned, namely +put them into ``Deferred`` list. + +runOnModule +""""""""""" +The algorithm is pretty simple: + +1. Put all module's functions into the *worklist*. + +2. Scan *worklist*'s functions twice: first enumerate only strong functions and +then only weak ones: + + 2.1. Loop body: take function from *worklist* (call it *FCur*) and try to + insert it into *FnTree*: check whether *FCur* is equal to one of functions + in *FnTree*. If there *is* equal function in *FnTree* (call it *FExists*): + merge function *FCur* with *FExists*. Otherwise add function from *worklist* + to *FnTree*. + +3. Once *worklist* scanning and merging operations is complete, check *Deferred* +list. If it is not empty: refill *worklist* contents with *Deferred* list and +do step 2 again, if *Deferred* is empty, then exit from method. + +Comparison and logarithmical search +""""""""""""""""""""""""""""""""""" +Let's recall our task: for every function *F* from module *M*, we have to find +equal functions *F`* in shortest time, and merge them into the single function. + +Defining total ordering among the functions set allows to organize functions +into the binary tree. The lookup procedure complexity would be estimated as +O(log(N)) in this case. But how to define *total-ordering*? + +We have to introduce a single rule applicable to every pair of functions, and +following this rule then evaluate which of them is greater. What kind of rule +it could be? Let's declare it as "compare" method, that returns one of 3 +possible values: + +-1, left is *less* than right, + +0, left and right are *equal*, + +1, left is *greater* than right. + +Of course it means, that we have to maintain +*strict and non-strict order relation properties*: + +* reflexivity (``a <= a``, ``a == a``, ``a >= a``), +* antisymmetry (if ``a <= b`` and ``b <= a`` then ``a == b``), +* transitivity (``a <= b`` and ``b <= c``, then ``a <= c``) +* asymmetry (if ``a < b``, then ``a > b`` or ``a == b``). + +As it was mentioned before, comparison routine consists of +"sub-comparison-routines", each of them also consists +"sub-comparison-routines", and so on, finally it ends up with a primitives +comparison. + +Below, we will use the next operations: + +#. ``cmpNumbers(number1, number2)`` is method that returns -1 if left is less + than right; 0, if left and right are equal; and 1 otherwise. + +#. ``cmpFlags(flag1, flag2)`` is hypothetical method that compares two flags. + The logic is the same as in ``cmpNumbers``, where ``true`` is 1, and + ``false`` is 0. + +The rest of article is based on *MergeFunctions.cpp* source code +(*/lib/Transforms/IPO/MergeFunctions.cpp*). We would like to ask +reader to keep this file open nearby, so we could use it as a reference for +further explanations. + +Now we're ready to proceed to the next chapter and see how it works. + +Functions comparison +==================== +At first, let's define how exactly we compare complex objects. + +Complex objects comparison (function, basic-block, etc) is mostly based on its +sub-objects comparison results. So it is similar to the next "tree" objects +comparison: + +#. For two trees *T1* and *T2* we perform *depth-first-traversal* and have + two sequences as a product: "*T1Items*" and "*T2Items*". + +#. Then compare chains "*T1Items*" and "*T2Items*" in + most-significant-item-first order. Result of items comparison would be the + result of *T1* and *T2* comparison itself. + +FunctionComparator::compare(void) +--------------------------------- +Brief look at the source code tells us, that comparison starts in +“``int FunctionComparator::compare(void)``†method. + +1. First parts to be compared are function's attributes and some properties that +outsides “attributes†term, but still could make function different without +changing its body. This part of comparison is usually done within simple +*cmpNumbers* or *cmpFlags* operations (e.g. +``cmpFlags(F1->hasGC(), F2->hasGC())``). Below is full list of function's +properties to be compared on this stage: + + * *Attributes* (those are returned by ``Function::getAttributes()`` + method). + + * *GC*, for equivalence, *RHS* and *LHS* should be both either without + *GC* or with the same one. + + * *Section*, just like a *GC*: *RHS* and *LHS* should be defined in the + same section. + + * *Variable arguments*. *LHS* and *RHS* should be both either with or + without *var-args*. + + * *Calling convention* should be the same. + +2. Function type. Checked by ``FunctionComparator::cmpType(Type*, Type*)`` +method. It checks return type and parameters type; the method itself will be +described later. + +3. Associate function formal parameters with each other. Then comparing function +bodies, if we see the usage of *LHS*'s *i*-th argument in *LHS*'s body, then, +we want to see usage of *RHS*'s *i*-th argument at the same place in *RHS*'s +body, otherwise functions are different. On this stage we grant the preference +to those we met later in function body (value we met first would be *less*). +This is done by “``FunctionComparator::cmpValues(const Value*, const Value*)``†+method (will be described a bit later). + +4. Function body comparison. As it written in method comments: + +“We do a CFG-ordered walk since the actual ordering of the blocks in the linked +list is immaterial. Our walk starts at the entry block for both functions, then +takes each block from each terminator in order. As an artifact, this also means +that unreachable blocks are ignored.†+ +So, using this walk we get BBs from *left* and *right* in the same order, and +compare them by “``FunctionComparator::compare(const BasicBlock*, const +BasicBlock*)``†method. + +We also associate BBs with each other, like we did it with function formal +arguments (see ``cmpValues`` method below). + +FunctionComparator::cmpType +--------------------------- +Consider how types comparison works. + +1. Coerce pointer to integer. If left type is a pointer, try to coerce it to the +integer type. It could be done if its address space is 0, or if address spaces +are ignored at all. Do the same thing for the right type. + +2. If left and right types are equal, return 0. Otherwise we need to give +preference to one of them. So proceed to the next step. + +3. If types are of different kind (different type IDs). Return result of type +IDs comparison, treating them as a numbers (use ``cmpNumbers`` operation). + +4. If types are vectors or integers, return result of their pointers comparison, +comparing them as numbers. + +5. Check whether type ID belongs to the next group (call it equivalent-group): + + * Void + + * Float + + * Double + + * X86_FP80 + + * FP128 + + * PPC_FP128 + + * Label + + * Metadata. + + If ID belongs to group above, return 0. Since it's enough to see that + types has the same ``TypeID``. No additional information is required. + +6. Left and right are pointers. Return result of address space comparison +(numbers comparison). + +7. Complex types (structures, arrays, etc.). Follow complex objects comparison +technique (see the very first paragraph of this chapter). Both *left* and +*right* are to be expanded and their element types will be checked the same +way. If we get -1 or 1 on some stage, return it. Otherwise return 0. + +8. Steps 1-6 describe all the possible cases, if we passed steps 1-6 and didn't +get any conclusions, then invoke ``llvm_unreachable``, since it's quite +unexpectable case. + +cmpValues(const Value*, const Value*) +------------------------------------- +Method that compares local values. + +This method gives us an answer on a very curious quesion: whether we could treat +local values as equal, and which value is greater otherwise. It's better to +start from example: + +Consider situation when we're looking at the same place in left function "*FL*" +and in right function "*FR*". And every part of *left* place is equal to the +corresponding part of *right* place, and (!) both parts use *Value* instances, +for example: + +.. code-block:: llvm + + instr0 i32 %LV ; left side, function FL + instr0 i32 %RV ; right side, function FR + +So, now our conclusion depends on *Value* instances comparison. + +Main purpose of this method is to determine relation between such values. + +What we expect from equal functions? At the same place, in functions "*FL*" and +"*FR*" we expect to see *equal* values, or values *defined* at the same place +in "*FL*" and "*FR*". + +Consider small example here: + +.. code-block:: llvm + + define void %f(i32 %pf0, i32 %pf1) { + instr0 i32 %pf0 instr1 i32 %pf1 instr2 i32 123 + } + +.. code-block:: llvm + + define void %g(i32 %pg0, i32 %pg1) { + instr0 i32 %pg0 instr1 i32 %pg0 instr2 i32 123 + } + +In this example, *pf0* is associated with *pg0*, *pf1* is associated with *pg1*, +and we also declare that *pf0* < *pf1*, and thus *pg0* < *pf1*. + +Instructions with opcode "*instr0*" would be *equal*, since their types and +opcodes are equal, and values are *associated*. + +Instruction with opcode "*instr1*" from *f* is *greater* than instruction with +opcode "*instr1*" from *g*; here we have equal types and opcodes, but "*pf1* is +greater than "*pg0*". + +And instructions with opcode "*instr2*" are equal, because their opcodes and +types are equal, and the same constant is used as a value. + +What we assiciate in cmpValues? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Function arguments. *i*-th argument from left function associated with + *i*-th argument from right function. +* BasicBlock instances. In basic-block enumeration loop we associate *i*-th + BasicBlock from the left function with *i*-th BasicBlock from the right + function. +* Instructions. +* Instruction operands. Note, we can meet *Value* here we have never seen + before. In this case it is not a function argument, nor *BasicBlock*, nor + *Instruction*. It is global value. It is constant, since its the only + supposed global here. Method also compares: +* Constants that are of the same type. +* If right constant could be losslessly bit-casted to the left one, then we + also compare them. + +How to implement cmpValues? +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +*Association* is a case of equality for us. We just treat such values as equal. +But, in general, we need to implement antisymmetric relation. As it was +mentioned above, to understand what is *less*, we can use order in which we +meet values. If both of values has the same order in function (met at the same +time), then treat values as *associated*. Otherwise – it depends on who was +first. + +Every time we run top-level compare method, we initialize two identical maps +(one for the left side, another one for the right side): + +``map sn_mapL, sn_mapR;`` + +The key of the map is the *Value* itself, the *value* – is its order (call it +*serial number*). + +To add value *V* we need to perform the next procedure: + +``sn_map.insert(std::make_pair(V, sn_map.size()));`` + +For the first *Value*, map will return *0*, for second *Value* map will return +*1*, and so on. + +Then we can check whether left and right values met at the same time with simple +comparison: + +``cmpNumbers(sn_mapL[Left], sn_mapR[Right]);`` + +Of course, we can combine insertion and comparison: + +.. code-block:: c++ + + std::pair + LeftRes = sn_mapL.insert(std::make_pair(Left, sn_mapL.size())), RightRes + = sn_mapR.insert(std::make_pair(Right, sn_mapR.size())); + return cmpNumbers(LeftRes.first->second, RightRes.first->second); + +Let's look, how whole method could be implemented. + +1. we have to start from the bad news. Consider function self and +cross-referencing cases: + +.. code-block:: c++ + + // self-reference unsigned fact0(unsigned n) { return n > 1 ? n + * fact0(n-1) : 1; } unsigned fact1(unsigned n) { return n > 1 ? n * + fact1(n-1) : 1; } + + // cross-reference unsigned ping(unsigned n) { return n!= 0 ? pong(n-1) : 0; + } unsigned pong(unsigned n) { return n!= 0 ? ping(n-1) : 0; } + +.. + + This comparison has been implemented in initial *MergeFunctions* pass + version. But, unfortunately, it is not transitive. And this is the only case + we can't convert to less-equal-greater comparison. It is a seldom case, 4-5 + functions of 10000 (checked on test-suite), and, we hope, reader would + forgive us for such a sacrifice in order to get the O(log(N)) pass time. + +2. If left/right *Value* is a constant, we have to compare them. Return 0 if it +is the same constant, or use ``cmpConstants`` method otherwise. + +3. If left/right is *InlineAsm* instance. Return result of *Value* pointers +comparison. + +4. Explicit association of *L* (left value) and *R* (right value). We need to +find out whether values met at the same time, and thus are *associated*. Or we +need to put the rule: when we treat *L* < *R*. Now it is easy: just return +result of numbers comparison: + +.. code-block:: c++ + + std::pair + LeftRes = sn_mapL.insert(std::make_pair(Left, sn_mapL.size())), + RightRes = sn_mapR.insert(std::make_pair(Right, sn_mapR.size())); + if (LeftRes.first->second == RightRes.first->second) return 0; + if (LeftRes.first->second < RightRes.first->second) return -1; + return 1; + +Now when *cmpValues* returns 0, we can proceed comparison procedure. Otherwise, +if we get (-1 or 1), we need to pass this result to the top level, and finish +comparison procedure. + +cmpConstants +------------ +Performs constants comparison as follows: + +1. Compare constant types using ``cmpType`` method. If result is -1 or 1, goto +step 2, otherwise proceed to step 3. + +2. If types are different, we still can check whether constants could be +losslessly bitcasted to each other. The further explanation is modification of +``canLosslesslyBitCastTo`` method. + + 2.1 Check whether constants are of the first class types + (``isFirstClassType`` check): + + 2.1.1. If both constants are *not* of the first class type: return result + of ``cmpType``. + + 2.1.2. Otherwise, if left type is not of the first class, return -1. If + right type is not of the first class, return 1. + + 2.1.3. If both types are of the first class type, proceed to the next step + (2.1.3.1). + + 2.1.3.1. If types are vectors, compare their bitwidth using the + *cmpNumbers*. If result is not 0, return it. + + 2.1.3.2. Different types, but not a vectors: + + * if both of them are pointers, good for us, we can proceed to step 3. + * if one of types is pointer, return result of *isPointer* flags + comparison (*cmpFlags* operation). + * otherwise we have no methods to prove bitcastability, and thus return + result of types comparison (-1 or 1). + +Steps below are for the case when types are equal, or case when constants are +bitcastable: + +3. One of constants is a "*null*" value. Return the result of +``cmpFlags(L->isNullValue, R->isNullValue)`` comparison. + +4. Compare value IDs, and return result if it is not 0: + +.. code-block:: c++ + + if (int Res = cmpNumbers(L->getValueID(), R->getValueID())) + return Res; + +5. Compare the contents of constants. The comparison depends on kind of +constants, but on this stage it is just a lexicographical comparison. Just see +how it was described in the beginning of "*Functions comparison*" paragraph. +Mathematically it is equal to the next case: we encode left constant and right +constant (with similar way *bitcode-writer* does). Then compare left code +sequence and right code sequence. + +compare(const BasicBlock*, const BasicBlock*) +--------------------------------------------- +Compares two *BasicBlock* instances. + +It enumerates instructions from left *BB* and right *BB*. + +1. It assigns serial numbers to the left and right instructions, using +``cmpValues`` method. + +2. If one of left or right is *GEP* (``GetElementPtr``), then treat *GEP* as +greater than other instructions, if both instructions are *GEPs* use ``cmpGEP`` +method for comparison. If result is -1 or 1, pass it to the top-level +comparison (return it). + + 3.1. Compare operations. Call ``cmpOperation`` method. If result is -1 or + 1, return it. + + 3.2. Compare number of operands, if result is -1 or 1, return it. + + 3.3. Compare operands themselves, use ``cmpValues`` method. Return result + if it is -1 or 1. + + 3.4. Compare type of operands, using ``cmpType`` method. Return result if + it is -1 or 1. + + 3.5. Proceed to the next instruction. + +4. We can finish instruction enumeration in 3 cases: + + 4.1. We reached the end of both left and right basic-blocks. We didn't + exit on steps 1-3, so contents is equal, return 0. + + 4.2. We have reached the end of the left basic-block. Return -1. + + 4.3. Return 1 (the end of the right basic block). + +cmpGEP +------ +Compares two GEPs (``getelementptr`` instructions). + +It differs from regular operations comparison with the only thing: possibility +to use ``accumulateConstantOffset`` method. + +So, if we get constant offset for both left and right *GEPs*, then compare it as +numbers, and return comparison result. + +Otherwise treat it like a regular operation (see previous paragraph). + +cmpOperation +------------ +Compares instruction opcodes and some important operation properties. + +1. Compare opcodes, if it differs return the result. + +2. Compare number of operands. If it differs – return the result. + +3. Compare operation types, use *cmpType*. All the same – if types are +different, return result. + +4. Compare *subclassOptionalData*, get it with ``getRawSubclassOptionalData`` +method, and compare it like a numbers. + +5. Compare operand types. + +6. For some particular instructions check equivalence (relation in our case) of +some significant attributes. For example we have to compare alignment for +``load`` instructions. + +O(log(N)) +--------- +Methods described above implement order relationship. And latter, could be used +for nodes comparison in a binary tree. So we can organize functions set into +the binary tree and reduce the cost of lookup procedure from +O(N*N) to O(log(N)). + +Merging process, mergeTwoFunctions +================================== +Once *MergeFunctions* detected that current function (*G*) is equal to one that +were analyzed before (function *F*) it calls ``mergeTwoFunctions(Function*, +Function*)``. + +Operation affects ``FnTree`` contents with next way: *F* will stay in +``FnTree``. *G* being equal to *F* will not be added to ``FnTree``. Calls of +*G* would be replaced with something else. It changes bodies of callers. So, +functions that calls *G* would be put into ``Deferred`` set and removed from +``FnTree``, and analyzed again. + +The approach is next: + +1. Most wished case: when we can use alias and both of *F* and *G* are weak. We +make both of them with aliases to the third strong function *H*. Actually *H* +is *F*. See below how it's made (but it's better to look straight into the +source code). Well, this is a case when we can just replace *G* with *F* +everywhere, we use ``replaceAllUsesWith`` operation here (*RAUW*). + +2. *F* could not be overridden, while *G* could. It would be good to do the +next: after merging the places where overridable function were used, still use +overridable stub. So try to make *G* alias to *F*, or create overridable tail +call wrapper around *F* and replace *G* with that call. + +3. Neither *F* nor *G* could be overridden. We can't use *RAUW*. We can just +change the callers: call *F* instead of *G*. That's what +``replaceDirectCallers`` does. + +Below is detailed body description. + +If “F†may be overridden +------------------------ +As follows from ``mayBeOverridden`` comments: “whether the definition of this +global may be replaced by something non-equivalent at link timeâ€. If so, thats +ok: we can use alias to *F* instead of *G* or change call instructions itself. + +HasGlobalAliases, removeUsers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +First consider the case when we have global aliases of one function name to +another. Our purpose is make both of them with aliases to the third strong +function. Though if we keep *F* alive and without major changes we can leave it +in ``FnTree``. Try to combine these two goals. + +Do stub replacement of *F* itself with an alias to *F*. + +1. Create stub function *H*, with the same name and attributes like function +*F*. It takes maximum alignment of *F* and *G*. + +2. Replace all uses of function *F* with uses of function *H*. It is the two +steps procedure instead. First of all, we must take into account, all functions +from whom *F* is called would be changed: since we change the call argument +(from *F* to *H*). If so we must to review these caller functions again after +this procedure. We remove callers from ``FnTree``, method with name +``removeUsers(F)`` does that (don't confuse with ``replaceAllUsesWith``): + + 2.1. ``Inside removeUsers(Value* + V)`` we go through the all values that use value *V* (or *F* in our context). + If value is instruction, we go to function that holds this instruction and + mark it as to-be-analyzed-again (put to ``Deferred`` set), we also remove + caller from ``FnTree``. + + 2.2. Now we can do the replacement: call ``F->replaceAllUsesWith(H)``. + +3. *H* (that now "officially" plays *F*'s role) is replaced with alias to *F*. +Do the same with *G*: replace it with alias to *F*. So finally everywhere *F* +was used, we use *H* and it is alias to *F*, and everywhere *G* was used we +also have alias to *F*. + +4. Set *F* linkage to private. Make it strong :-) + +No global aliases, replaceDirectCallers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If global aliases are not supported. We call ``replaceDirectCallers`` then. Just +go through all calls of *G* and replace it with calls of *F*. If you look into +method you will see that it scans all uses of *G* too, and if use is callee (if +user is call instruction and *G* is used as what to be called), we replace it +with use of *F*. + +If “F†could not be overridden, fix it! +""""""""""""""""""""""""""""""""""""""" + +We call ``writeThunkOrAlias(Function *F, Function *G)``. Here we try to replace +*G* with alias to *F* first. Next conditions are essential: + +* target should support global aliases, +* the address itself of *G* should be not significant, not named and not + referenced anywhere, +* function should come with external, local or weak linkage. + +Otherwise we write thunk: some wrapper that has *G's* interface and calls *F*, +so *G* could be replaced with this wrapper. + +*writeAlias* + +As follows from *llvm* reference: + +“Aliases act as *second name* for the aliasee valueâ€. So we just want to create +second name for *F* and use it instead of *G*: + +1. create global alias itself (*GA*), + +2. adjust alignment of *F* so it must be maximum of current and *G's* alignment; + +3. replace uses of *G*: + + 3.1. first mark all callers of *G* as to-be-analyzed-again, using + ``removeUsers`` method (see chapter above), + + 3.2. call ``G->replaceAllUsesWith(GA)``. + +4. Get rid of *G*. + +*writeThunk* + +As it written in method comments: + +“Replace G with a simple tail call to bitcast(F). Also replace direct uses of G +with bitcast(F). Deletes G.†+ +In general it does the same as usual when we want to replace callee, except the +first point: + +1. We generate tail call wrapper around *F*, but with interface that allows use +it instead of *G*. + +2. “As-usualâ€: ``removeUsers`` and ``replaceAllUsesWith`` then. + +3. Get rid of *G*. + +That's it. +========== +We have described how to detect equal functions, and how to merge them, and in +first chapter we have described how it works all-together. Author hopes, reader +have some picture from now, and it helps him improve and debug ­this pass. + +Reader is welcomed to send us any questions and proposals ;-) diff --git a/docs/Passes.rst b/docs/Passes.rst index 9f40092..cc0a853 100644 --- a/docs/Passes.rst +++ b/docs/Passes.rst @@ -891,17 +891,24 @@ calls, or transforming sets of stores into ``memset``\ s. This pass looks for equivalent functions that are mergable and folds them. -A hash is computed from the function, based on its type and number of basic -blocks. +Total-ordering is introduced among the functions set: we define comparison +that answers for every two functions which of them is greater. It allows to +arrange functions into the binary tree. -Once all hashes are computed, we perform an expensive equality comparison on -each function pair. This takes n^2/2 comparisons per bucket, so it's important -that the hash function be high quality. The equality comparison iterates -through each instruction in each basic block. +For every new function we check for equivalent in tree. -When a match is found the functions are folded. If both functions are -overridable, we move the functionality into a new internal function and leave -two overridable thunks to it. +If equivalent exists we fold such functions. If both functions are overridable, +we move the functionality into a new internal function and leave two +overridable thunks to it. + +If there is no equivalent, then we add this function to tree. + +Lookup routine has O(log(n)) complexity, while whole merging process has +complexity of O(n*log(n)). + +Read +:doc:`this ` +article for more details. ``-mergereturn``: Unify function exit nodes ------------------------------------------- @@ -1112,13 +1119,6 @@ useful when diffing the effect of an optimization because deleting an unnamed instruction can change all other instruction numbering, making the diff very noisy. -``-preverify``: Preliminary module verification ------------------------------------------------ - -Ensures that the module is in the form required by the :ref:`Module Verifier -` pass. Running the verifier runs this pass automatically, so -there should be no need to use it directly. - .. _passes-verify: ``-verify``: Module Verifier diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst index 8ac9afe..3f4f72a 100644 --- a/docs/Phabricator.rst +++ b/docs/Phabricator.rst @@ -66,7 +66,8 @@ To upload a new patch: * Leave the drop down on *Create a new Revision...* and click *Continue*. * Enter a descriptive title and summary; add reviewers and mailing lists that you want to be included in the review. If your patch is - for LLVM, cc llvm-commits; if your patch is for Clang, cc cfe-commits. + for LLVM, add llvm-commits as a subscriber; if your patch is for Clang, + add cfe-commits. * Click *Save*. To submit an updated patch: diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index 85a4ad8..753e658 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -488,6 +488,9 @@ gathered, use the '``-stats``' option: $ opt -stats -mypassname < program.bc > /dev/null ... statistics output ... +Note that in order to use the '``-stats``' option, LLVM must be +compiled with assertions enabled. + When running ``opt`` on a C file from the SPEC benchmark suite, it gives a report that looks like this: @@ -1408,7 +1411,7 @@ llvm/ADT/IntervalMap.h IntervalMap is a compact map for small keys and values. It maps key intervals instead of single keys, and it will automatically coalesce adjacent intervals. -When then map only contains a few intervals, they are stored in the map object +When the map only contains a few intervals, they are stored in the map object itself to avoid allocations. The IntervalMap iterators are quite big, so they should not be passed around as @@ -2480,6 +2483,76 @@ ensures that the first bytes of ``User`` (if interpreted as a pointer) never has the LSBit set. (Portability is relying on the fact that all known compilers place the ``vptr`` in the first word of the instances.) +.. _polymorphism: + +Designing Type Hiercharies and Polymorphic Interfaces +----------------------------------------------------- + +There are two different design patterns that tend to result in the use of +virtual dispatch for methods in a type hierarchy in C++ programs. The first is +a genuine type hierarchy where different types in the hierarchy model +a specific subset of the functionality and semantics, and these types nest +strictly within each other. Good examples of this can be seen in the ``Value`` +or ``Type`` type hierarchies. + +A second is the desire to dispatch dynamically across a collection of +polymorphic interface implementations. This latter use case can be modeled with +virtual dispatch and inheritance by defining an abstract interface base class +which all implementations derive from and override. However, this +implementation strategy forces an **"is-a"** relationship to exist that is not +actually meaningful. There is often not some nested hierarchy of useful +generalizations which code might interact with and move up and down. Instead, +there is a singular interface which is dispatched across a range of +implementations. + +The preferred implementation strategy for the second use case is that of +generic programming (sometimes called "compile-time duck typing" or "static +polymorphism"). For example, a template over some type parameter ``T`` can be +instantiated across any particular implementation that conforms to the +interface or *concept*. A good example here is the highly generic properties of +any type which models a node in a directed graph. LLVM models these primarily +through templates and generic programming. Such templates include the +``LoopInfoBase`` and ``DominatorTreeBase``. When this type of polymorphism +truly needs **dynamic** dispatch you can generalize it using a technique +called *concept-based polymorphism*. This pattern emulates the interfaces and +behaviors of templates using a very limited form of virtual dispatch for type +erasure inside its implementation. You can find examples of this technique in +the ``PassManager.h`` system, and there is a more detailed introduction to it +by Sean Parent in several of his talks and papers: + +#. `Inheritance Is The Base Class of Evil + `_ + - The GoingNative 2013 talk describing this technique, and probably the best + place to start. +#. `Value Semantics and Concepts-based Polymorphism + `_ - The C++Now! 2012 talk + describing this technique in more detail. +#. `Sean Parent's Papers and Presentations + `_ + - A Github project full of links to slides, video, and sometimes code. + +When deciding between creating a type hierarchy (with either tagged or virtual +dispatch) and using templates or concepts-based polymorphism, consider whether +there is some refinement of an abstract base class which is a semantically +meaningful type on an interface boundary. If anything more refined than the +root abstract interface is meaningless to talk about as a partial extension of +the semantic model, then your use case likely fits better with polymorphism and +you should avoid using virtual dispatch. However, there may be some exigent +circumstances that require one technique or the other to be used. + +If you do need to introduce a type hierarchy, we prefer to use explicitly +closed type hierarchies with manual tagged dispatch and/or RTTI rather than the +open inheritance model and virtual dispatch that is more common in C++ code. +This is because LLVM rarely encourages library consumers to extend its core +types, and leverages the closed and tag-dispatched nature of its hierarchies to +generate significantly more efficient code. We have also found that a large +amount of our usage of type hierarchies fits better with tag-based pattern +matching rather than dynamic dispatch across a common interface. Within LLVM we +have built custom helpers to facilitate this design. See this document's +section on :ref:`isa and dyn_cast ` and our :doc:`detailed document +` which describes how you can implement this +pattern for use with the LLVM helpers. + .. _coreclasses: The Core LLVM Class Hierarchy Reference diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index be2954c..6a38363 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,12 +1,12 @@ ====================== -LLVM 3.5 Release Notes +LLVM 3.7 Release Notes ====================== .. contents:: :local: .. warning:: - These are in-progress notes for the upcoming LLVM 3.6 release. You may + These are in-progress notes for the upcoming LLVM 3.7 release. You may prefer the `LLVM 3.5 Release Notes `_. @@ -15,7 +15,7 @@ Introduction ============ This document contains the release notes for the LLVM Compiler Infrastructure, -release 3.6. Here we describe the status of LLVM, including major improvements +release 3.7. 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 `_. @@ -41,10 +41,8 @@ Non-comprehensive list of changes in this release functionality, or simply have a lot to talk about), see the `NOTE` below for adding a new subsection. -* Support for AuroraUX has been removed. - -* Added support for a `native object file-based bitcode wrapper format - `_. +* The minimum required Visual Studio version for building LLVM is now 2013 + Update 4. * ... next change ... @@ -67,19 +65,27 @@ Changes to the ARM Backend Changes to the MIPS Target -------------------------- -During this release ... + During this release ... + Changes to the PowerPC Target ----------------------------- -During this release ... + During this release ... + + +Changes to the OCaml bindings +----------------------------- + + During this release ... + -External Open Source Projects Using LLVM 3.6 +External Open Source Projects Using LLVM 3.7 ============================================ 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.6. +projects that have already been updated to work with LLVM 3.7. * A project diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst index 3a5fa6e..350604c 100644 --- a/docs/SourceLevelDebugging.rst +++ b/docs/SourceLevelDebugging.rst @@ -1807,7 +1807,6 @@ tag is one of: * DW_TAG_subrange_type * DW_TAG_base_type * DW_TAG_const_type -* DW_TAG_constant * DW_TAG_file_type * DW_TAG_namelist * DW_TAG_packed_type diff --git a/docs/StackMaps.rst b/docs/StackMaps.rst index bd0fb94..43c60c9 100644 --- a/docs/StackMaps.rst +++ b/docs/StackMaps.rst @@ -221,6 +221,13 @@ lowered according to the calling convention specified at the intrinsic's callsite. Variants of the intrinsic with non-void return type also return a value according to calling convention. +On PowerPC, note that ```` must be the actual intended target of +the indirect call. Specifically, even when compiling for the ELF V1 ABI, +```` is not the function-descriptor address normally used as the C/C++ +function-pointer representation. As a result, the call target must be local +because no adjustment or restoration of the TOC pointer (in register r2) will +be performed. + Requesting zero patch point arguments is valid. In this case, all variable operands are handled just like ``llvm.experimental.stackmap.*``. The difference is that space will diff --git a/docs/Statepoints.rst b/docs/Statepoints.rst new file mode 100644 index 0000000..9741c93 --- /dev/null +++ b/docs/Statepoints.rst @@ -0,0 +1,580 @@ +===================================== +Garbage Collection Safepoints in LLVM +===================================== + +.. contents:: + :local: + :depth: 2 + +Status +======= + +This document describes a set of experimental extensions to LLVM. Use +with caution. Because the intrinsics have experimental status, +compatibility across LLVM releases is not guaranteed. + +LLVM currently supports an alternate mechanism for conservative +garbage collection support using the ``gcroot`` intrinsic. The mechanism +described here shares little in common with the alternate ``gcroot`` +implementation and it is hoped that this mechanism will eventually +replace the gc_root mechanism. + +Overview +======== + +To collect dead objects, garbage collectors must be able to identify +any references to objects contained within executing code, and, +depending on the collector, potentially update them. The collector +does not need this information at all points in code - that would make +the problem much harder - but only at well-defined points in the +execution known as 'safepoints' For most collectors, it is sufficient +to track at least one copy of each unique pointer value. However, for +a collector which wishes to relocate objects directly reachable from +running code, a higher standard is required. + +One additional challenge is that the compiler may compute intermediate +results ("derived pointers") which point outside of the allocation or +even into the middle of another allocation. The eventual use of this +intermediate value must yield an address within the bounds of the +allocation, but such "exterior derived pointers" may be visible to the +collector. Given this, a garbage collector can not safely rely on the +runtime value of an address to indicate the object it is associated +with. If the garbage collector wishes to move any object, the +compiler must provide a mapping, for each pointer, to an indication of +its allocation. + +To simplify the interaction between a collector and the compiled code, +most garbage collectors are organized in terms of three abstractions: +load barriers, store barriers, and safepoints. + +#. A load barrier is a bit of code executed immediately after the + machine load instruction, but before any use of the value loaded. + Depending on the collector, such a barrier may be needed for all + loads, merely loads of a particular type (in the original source + language), or none at all. + +#. Analogously, a store barrier is a code fragement that runs + immediately before the machine store instruction, but after the + computation of the value stored. The most common use of a store + barrier is to update a 'card table' in a generational garbage + collector. + +#. A safepoint is a location at which pointers visible to the compiled + code (i.e. currently in registers or on the stack) are allowed to + change. After the safepoint completes, the actual pointer value + may differ, but the 'object' (as seen by the source language) + pointed to will not. + + Note that the term 'safepoint' is somewhat overloaded. It refers to + both the location at which the machine state is parsable and the + coordination protocol involved in bring application threads to a + point at which the collector can safely use that information. The + term "statepoint" as used in this document refers exclusively to the + former. + +This document focuses on the last item - compiler support for +safepoints in generated code. We will assume that an outside +mechanism has decided where to place safepoints. From our +perspective, all safepoints will be function calls. To support +relocation of objects directly reachable from values in compiled code, +the collector must be able to: + +#. identify every copy of a pointer (including copies introduced by + the compiler itself) at the safepoint, +#. identify which object each pointer relates to, and +#. potentially update each of those copies. + +This document describes the mechanism by which an LLVM based compiler +can provide this information to a language runtime/collector, and +ensure that all pointers can be read and updated if desired. The +heart of the approach is to construct (or rewrite) the IR in a manner +where the possible updates performed by the garbage collector are +explicitly visible in the IR. Doing so requires that we: + +#. create a new SSA value for each potentially relocated pointer, and + ensure that no uses of the original (non relocated) value is + reachable after the safepoint, +#. specify the relocation in a way which is opaque to the compiler to + ensure that the optimizer can not introduce new uses of an + unrelocated value after a statepoint. This prevents the optimizer + from performing unsound optimizations. +#. recording a mapping of live pointers (and the allocation they're + associated with) for each statepoint. + +At the most abstract level, inserting a safepoint can be thought of as +replacing a call instruction with a call to a multiple return value +function which both calls the original target of the call, returns +it's result, and returns updated values for any live pointers to +garbage collected objects. + + Note that the task of identifying all live pointers to garbage + collected values, transforming the IR to expose a pointer giving the + base object for every such live pointer, and inserting all the + intrinsics correctly is explicitly out of scope for this document. + The recommended approach is to use the :ref:`utility passes + ` described below. + +This abstract function call is concretely represented by a sequence of +intrinsic calls known collectively as a "statepoint relocation sequence". + +Let's consider a simple call in LLVM IR: + +.. code-block:: llvm + + define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) + gc "statepoint-example" { + call void ()* @foo() + ret i8 addrspace(1)* %obj + } + +Depending on our language we may need to allow a safepoint during the execution +of ``foo``. If so, we need to let the collector update local values in the +current frame. If we don't, we'll be accessing a potential invalid reference +once we eventually return from the call. + +In this example, we need to relocate the SSA value ``%obj``. Since we can't +actually change the value in the SSA value ``%obj``, we need to introduce a new +SSA value ``%obj.relocated`` which represents the potentially changed value of +``%obj`` after the safepoint and update any following uses appropriately. The +resulting relocation sequence is: + +.. code-block:: llvm + + define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) + gc "statepoint-example" { + %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + ret i8 addrspace(1)* %obj.relocated + } + +Ideally, this sequence would have been represented as a M argument, N +return value function (where M is the number of values being +relocated + the original call arguments and N is the original return +value + each relocated value), but LLVM does not easily support such a +representation. + +Instead, the statepoint intrinsic marks the actual site of the +safepoint or statepoint. The statepoint returns a token value (which +exists only at compile time). To get back the original return value +of the call, we use the ``gc.result`` intrinsic. To get the relocation +of each pointer in turn, we use the ``gc.relocate`` intrinsic with the +appropriate index. Note that both the ``gc.relocate`` and ``gc.result`` are +tied to the statepoint. The combination forms a "statepoint relocation +sequence" and represents the entitety of a parseable call or 'statepoint'. + +When lowered, this example would generate the following x86 assembly: + +.. code-block:: gas + + .globl test1 + .align 16, 0x90 + pushq %rax + callq foo + .Ltmp1: + movq (%rsp), %rax # This load is redundant (oops!) + popq %rdx + retq + +Each of the potentially relocated values has been spilled to the +stack, and a record of that location has been recorded to the +:ref:`Stack Map section `. If the garbage collector +needs to update any of these pointers during the call, it knows +exactly what to change. + +The relevant parts of the StackMap section for our example are: + +.. code-block:: gas + + # This describes the call site + # Stack Maps: callsite 2882400000 + .quad 2882400000 + .long .Ltmp1-test1 + .short 0 + # .. 8 entries skipped .. + # This entry describes the spill slot which is directly addressable + # off RSP with offset 0. Given the value was spilled with a pushq, + # that makes sense. + # Stack Maps: Loc 8: Direct RSP [encoding: .byte 2, .byte 8, .short 7, .int 0] + .byte 2 + .byte 8 + .short 7 + .long 0 + +This example was taken from the tests for the :ref:`RewriteStatepointsForGC` utility pass. As such, it's full StackMap can be easily examined with the following command. + +.. code-block:: bash + + opt -rewrite-statepoints-for-gc test/Transforms/RewriteStatepointsForGC/basics.ll -S | llc -debug-only=stackmaps + + + + + +Intrinsics +=========== + +'llvm.experimental.gc.statepoint' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i32 + @llvm.experimental.gc.statepoint(func_type , + i64 <#call args>. i64 , + ... (call parameters), + i64 <# deopt args>, ... (deopt parameters), + ... (gc parameters)) + +Overview: +""""""""" + +The statepoint intrinsic represents a call which is parse-able by the +runtime. + +Operands: +""""""""" + +The 'target' operand is the function actually being called. The +target can be specified as either a symbolic LLVM function, or as an +arbitrary Value of appropriate function type. Note that the function +type must match the signature of the callee and the types of the 'call +parameters' arguments. + +The '#call args' operand is the number of arguments to the actual +call. It must exactly match the number of arguments passed in the +'call parameters' variable length section. + +The 'unused' operand is unused and likely to be removed. Please do +not use. + +The 'call parameters' arguments are simply the arguments which need to +be passed to the call target. They will be lowered according to the +specified calling convention and otherwise handled like a normal call +instruction. The number of arguments must exactly match what is +specified in '# call args'. The types must match the signature of +'target'. + +The 'deopt parameters' arguments contain an arbitrary list of Values +which is meaningful to the runtime. The runtime may read any of these +values, but is assumed not to modify them. If the garbage collector +might need to modify one of these values, it must also be listed in +the 'gc pointer' argument list. The '# deopt args' field indicates +how many operands are to be interpreted as 'deopt parameters'. + +The 'gc parameters' arguments contain every pointer to a garbage +collector object which potentially needs to be updated by the garbage +collector. Note that the argument list must explicitly contain a base +pointer for every derived pointer listed. The order of arguments is +unimportant. Unlike the other variable length parameter sets, this +list is not length prefixed. + +Semantics: +"""""""""" + +A statepoint is assumed to read and write all memory. As a result, +memory operations can not be reordered past a statepoint. It is +illegal to mark a statepoint as being either 'readonly' or 'readnone'. + +Note that legal IR can not perform any memory operation on a 'gc +pointer' argument of the statepoint in a location statically reachable +from the statepoint. Instead, the explicitly relocated value (from a +``gc.relocate``) must be used. + +'llvm.experimental.gc.result' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare type* + @llvm.experimental.gc.result(i32 %statepoint_token) + +Overview: +""""""""" + +``gc.result`` extracts the result of the original call instruction +which was replaced by the ``gc.statepoint``. The ``gc.result`` +intrinsic is actually a family of three intrinsics due to an +implementation limitation. Other than the type of the return value, +the semantics are the same. + +Operands: +""""""""" + +The first and only argument is the ``gc.statepoint`` which starts +the safepoint sequence of which this ``gc.result`` is a part. +Despite the typing of this as a generic i32, *only* the value defined +by a ``gc.statepoint`` is legal here. + +Semantics: +"""""""""" + +The ``gc.result`` represents the return value of the call target of +the ``statepoint``. The type of the ``gc.result`` must exactly match +the type of the target. If the call target returns void, there will +be no ``gc.result``. + +A ``gc.result`` is modeled as a 'readnone' pure function. It has no +side effects since it is just a projection of the return value of the +previous call represented by the ``gc.statepoint``. + +'llvm.experimental.gc.relocate' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare + @llvm.experimental.gc.relocate(i32 %statepoint_token, + i32 %base_offset, + i32 %pointer_offset) + +Overview: +""""""""" + +A ``gc.relocate`` returns the potentially relocated value of a pointer +at the safepoint. + +Operands: +""""""""" + +The first argument is the ``gc.statepoint`` which starts the +safepoint sequence of which this ``gc.relocation`` is a part. +Despite the typing of this as a generic i32, *only* the value defined +by a ``gc.statepoint`` is legal here. + +The second argument is an index into the statepoints list of arguments +which specifies the base pointer for the pointer being relocated. +This index must land within the 'gc parameter' section of the +statepoint's argument list. + +The third argument is an index into the statepoint's list of arguments +which specify the (potentially) derived pointer being relocated. It +is legal for this index to be the same as the second argument +if-and-only-if a base pointer is being relocated. This index must land +within the 'gc parameter' section of the statepoint's argument list. + +Semantics: +"""""""""" + +The return value of ``gc.relocate`` is the potentially relocated value +of the pointer specified by it's arguments. It is unspecified how the +value of the returned pointer relates to the argument to the +``gc.statepoint`` other than that a) it points to the same source +language object with the same offset, and b) the 'based-on' +relationship of the newly relocated pointers is a projection of the +unrelocated pointers. In particular, the integer value of the pointer +returned is unspecified. + +A ``gc.relocate`` is modeled as a ``readnone`` pure function. It has no +side effects since it is just a way to extract information about work +done during the actual call modeled by the ``gc.statepoint``. + +.. _statepoint-stackmap-format: + +Stack Map Format +================ + +Locations for each pointer value which may need read and/or updated by +the runtime or collector are provided via the :ref:`Stack Map format +` specified in the PatchPoint documentation. + +Each statepoint generates the following Locations: + +* Constant which describes number of following deopt *Locations* (not + operands) +* Variable number of Locations, one for each deopt parameter listed in + the IR statepoint (same number as described by previous Constant) +* Variable number of Locations pairs, one pair for each unique pointer + which needs relocated. The first Location in each pair describes + the base pointer for the object. The second is the derived pointer + actually being relocated. It is guaranteed that the base pointer + must also appear explicitly as a relocation pair if used after the + statepoint. There may be fewer pairs then gc parameters in the IR + statepoint. Each *unique* pair will occur at least once; duplicates + are possible. + +Note that the Locations used in each section may describe the same +physical location. e.g. A stack slot may appear as a deopt location, +a gc base pointer, and a gc derived pointer. + +The ID field of the 'StkMapRecord' for a statepoint is meaningless and +it's value is explicitly unspecified. + +The LiveOut section of the StkMapRecord will be empty for a statepoint +record. + +Safepoint Semantics & Verification +================================== + +The fundamental correctness property for the compiled code's +correctness w.r.t. the garbage collector is a dynamic one. It must be +the case that there is no dynamic trace such that a operation +involving a potentially relocated pointer is observably-after a +safepoint which could relocate it. 'observably-after' is this usage +means that an outside observer could observe this sequence of events +in a way which precludes the operation being performed before the +safepoint. + +To understand why this 'observable-after' property is required, +consider a null comparison performed on the original copy of a +relocated pointer. Assuming that control flow follows the safepoint, +there is no way to observe externally whether the null comparison is +performed before or after the safepoint. (Remember, the original +Value is unmodified by the safepoint.) The compiler is free to make +either scheduling choice. + +The actual correctness property implemented is slightly stronger than +this. We require that there be no *static path* on which a +potentially relocated pointer is 'observably-after' it may have been +relocated. This is slightly stronger than is strictly necessary (and +thus may disallow some otherwise valid programs), but greatly +simplifies reasoning about correctness of the compiled code. + +By construction, this property will be upheld by the optimizer if +correctly established in the source IR. This is a key invariant of +the design. + +The existing IR Verifier pass has been extended to check most of the +local restrictions on the intrinsics mentioned in their respective +documentation. The current implementation in LLVM does not check the +key relocation invariant, but this is ongoing work on developing such +a verifier. Please ask on llvmdev if you're interested in +experimenting with the current version. + +.. _statepoint-utilities: + +Utility Passes for Safepoint Insertion +====================================== + +.. _RewriteStatepointsForGC: + +RewriteStatepointsForGC +^^^^^^^^^^^^^^^^^^^^^^^^ + +The pass RewriteStatepointsForGC transforms a functions IR by replacing a +``gc.statepoint`` (with an optional ``gc.result``) with a full relocation +sequence, including all required ``gc.relocates``. To function, the pass +requires that the GC strategy specified for the function be able to reliably +distinguish between GC references and non-GC references in IR it is given. + +As an example, given this code: + +.. code-block:: llvm + + define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) + gc "statepoint-example" { + call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + ret i8 addrspace(1)* %obj + } + +The pass would produce this IR: + +.. code-block:: llvm + + define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) + gc "statepoint-example" { + %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + ret i8 addrspace(1)* %obj.relocated + } + +In the above examples, the addrspace(1) marker on the pointers is the mechanism +that the ``statepoint-example`` GC strategy uses to distinguish references from +non references. Address space 1 is not globally reserved for this purpose. + +This pass can be used an utility function by a language frontend that doesn't +want to manually reason about liveness, base pointers, or relocation when +constructing IR. As currently implemented, RewriteStatepointsForGC must be +run after SSA construction (i.e. mem2ref). + + +In practice, RewriteStatepointsForGC can be run much later in the pass +pipeline, after most optimization is already done. This helps to improve +the quality of the generated code when compiled with garbage collection support. +In the long run, this is the intended usage model. At this time, a few details +have yet to be worked out about the semantic model required to guarantee this +is always correct. As such, please use with caution and report bugs. + +.. _PlaceSafepoints: + +PlaceSafepoints +^^^^^^^^^^^^^^^^ + +The pass PlaceSafepoints transforms a function's IR by replacing any call or +invoke instructions with appropriate ``gc.statepoint`` and ``gc.result`` pairs, +and inserting safepoint polls sufficient to ensure running code checks for a +safepoint request on a timely manner. This pass is expected to be run before +RewriteStatepointsForGC and thus does not produce full relocation sequences. + +As an example, given input IR of the following: + +.. code-block:: llvm + + define void @test() gc "statepoint-example" { + call void @foo() + ret void + } + + declare void @do_safepoint() + define void @gc.safepoint_poll() { + call void @do_safepoint() + ret void + } + + +This pass would produce the following IR: + +.. code-block:: llvm + + define void @test() gc "statepoint-example" { + %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + ret void + } + +In this case, we've added an (unconditional) entry safepoint poll and converted the call into a ``gc.statepoint``. Note that despite appearances, the entry poll is not necessarily redundant. We'd have to know that ``foo`` and ``test`` were not mutually recursive for the poll to be redundant. In practice, you'd probably want to your poll definition to contain a conditional branch of some form. + + +At the moment, PlaceSafepoints can insert safepoint polls at method entry and +loop backedges locations. Extending this to work with return polls would be +straight forward if desired. + +PlaceSafepoints includes a number of optimizations to avoid placing safepoint +polls at particular sites unless needed to ensure timely execution of a poll +under normal conditions. PlaceSafepoints does not attempt to ensure timely +execution of a poll under worst case conditions such as heavy system paging. + +The implementation of a safepoint poll action is specified by looking up a +function of the name ``gc.safepoint_poll`` in the containing Module. The body +of this function is inserted at each poll site desired. While calls or invokes +inside this method are transformed to a ``gc.statepoints``, recursive poll +insertion is not performed. + +If you are scheduling the RewriteStatepointsForGC pass late in the pass order, +you should probably schedule this pass immediately before it. The exception +would be if you need to preserve abstract frame information (e.g. for +deoptimization or introspection) at safepoints. In that case, ask on the +llvmdev mailing list for suggestions. + + +Bugs and Enhancements +===================== + +Currently known bugs and enhancements under consideration can be +tracked by performing a `bugzilla search +`_ +for [Statepoint] in the summary field. When filing new bugs, please +use this tag so that interested parties see the newly filed bug. As +with most LLVM features, design discussions take place on `llvmdev +`_, and patches +should be sent to `llvm-commits +`_ for review. + diff --git a/docs/TableGen/index.rst b/docs/TableGen/index.rst index cda41b5..9526240 100644 --- a/docs/TableGen/index.rst +++ b/docs/TableGen/index.rst @@ -123,7 +123,6 @@ this (at the time of this writing): bit hasCtrlDep = 0; bit isNotDuplicable = 0; bit hasSideEffects = 0; - bit neverHasSideEffects = 0; InstrItinClass Itinerary = NoItinerary; string Constraints = ""; string DisableEncoding = ""; diff --git a/docs/WritingAnLLVMPass.rst b/docs/WritingAnLLVMPass.rst index ef2b953..1d5a52f 100644 --- a/docs/WritingAnLLVMPass.rst +++ b/docs/WritingAnLLVMPass.rst @@ -853,7 +853,7 @@ Example implementations of ``getAnalysisUsage`` // This example modifies the program, but does not modify the CFG void LICM::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); - AU.addRequired(); + AU.addRequired(); } .. _writing-an-llvm-pass-getAnalysis: @@ -870,7 +870,7 @@ you want, and returns a reference to that pass. For example: .. code-block:: c++ bool LICM::runOnFunction(Function &F) { - LoopInfo &LI = getAnalysis(); + LoopInfo &LI = getAnalysis().getLoopInfo(); //... } diff --git a/docs/conf.py b/docs/conf.py index 659c3e0..1897282 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,9 +47,9 @@ copyright = u'2003-2014, LLVM Project' # built documents. # # The short X.Y version. -version = '3.6' +version = '3.7' # The full version, including alpha/beta/rc tags. -release = '3.6' +release = '3.7' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.rst index 5ac5443..56567db 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -199,6 +199,8 @@ For developers of applications which use LLVM as a library. (`classes `_) (`tarball `_) +`Documentation for Go bindings `_ + `ViewVC Repository Browser `_ .. @@ -240,6 +242,9 @@ For API clients and LLVM developers. InAlloca BigEndianNEON CoverageMappingFormat + Statepoints + MergeFunctions + BitSets :doc:`WritingAnLLVMPass` Information on how to write LLVM transformations and analyses. @@ -332,6 +337,16 @@ For API clients and LLVM developers. :doc:`CoverageMappingFormat` This describes the format and encoding used for LLVM’s code coverage mapping. +:doc:`Statepoints` + This describes a set of experimental extensions for garbage + collection support. + +:doc:`MergeFunctions` + Describes functions merging optimization. + +:doc:`InAlloca` + Description of the ``inalloca`` argument attribute. + Development Process Documentation ================================= diff --git a/docs/tutorial/LangImpl1.rst b/docs/tutorial/LangImpl1.rst index a2c5eee..f4b0191 100644 --- a/docs/tutorial/LangImpl1.rst +++ b/docs/tutorial/LangImpl1.rst @@ -73,14 +73,21 @@ in the various pieces. The structure of the tutorial is: about this is how easy and trivial it is to construct SSA form in LLVM: no, LLVM does *not* require your front-end to construct SSA form! -- `Chapter #8 `_: Conclusion and other useful LLVM +- `Chapter #8 `_: Extending the Language: Debug + Information - Having built a decent little programming language with + control flow, functions and mutable variables, we consider what it + takes to add debug information to standalone executables. This debug + information will allow you to set breakpoints in Kaleidoscope + functions, print out argument variables, and call functions - all + from within the debugger! +- `Chapter #9 `_: Conclusion and other useful LLVM tidbits - This chapter wraps up the series by talking about potential ways to extend the language, but also includes a bunch of pointers to info about "special topics" like adding garbage collection support, exceptions, debugging, support for "spaghetti stacks", and a bunch of other tips and tricks. -By the end of the tutorial, we'll have written a bit less than 700 lines +By the end of the tutorial, we'll have written a bit less than 1000 lines of non-comment, non-blank, lines of code. With this small amount of code, we'll have built up a very reasonable compiler for a non-trivial language including a hand-written lexer, parser, AST, as well as code diff --git a/docs/tutorial/LangImpl4.rst b/docs/tutorial/LangImpl4.rst index aa469ca..cdaac63 100644 --- a/docs/tutorial/LangImpl4.rst +++ b/docs/tutorial/LangImpl4.rst @@ -428,7 +428,7 @@ the LLVM JIT and optimizer. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl5.rst b/docs/tutorial/LangImpl5.rst index 2a3a4ce..72e34b1 100644 --- a/docs/tutorial/LangImpl5.rst +++ b/docs/tutorial/LangImpl5.rst @@ -736,7 +736,7 @@ the if/then/else and for expressions.. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl6.rst b/docs/tutorial/LangImpl6.rst index cdceb03..bf78bde 100644 --- a/docs/tutorial/LangImpl6.rst +++ b/docs/tutorial/LangImpl6.rst @@ -729,7 +729,7 @@ the if/then/else and for expressions.. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl7.rst b/docs/tutorial/LangImpl7.rst index c4c7233..c445908 100644 --- a/docs/tutorial/LangImpl7.rst +++ b/docs/tutorial/LangImpl7.rst @@ -847,7 +847,7 @@ mutable variables and var/in support. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy @@ -856,5 +856,5 @@ Here is the code: .. literalinclude:: ../../examples/Kaleidoscope/Chapter7/toy.cpp :language: c++ -`Next: Conclusion and other useful LLVM tidbits `_ +`Next: Adding Debug Information `_ diff --git a/docs/tutorial/LangImpl8.rst b/docs/tutorial/LangImpl8.rst index 6f69493..4473035 100644 --- a/docs/tutorial/LangImpl8.rst +++ b/docs/tutorial/LangImpl8.rst @@ -1,267 +1,459 @@ -====================================================== -Kaleidoscope: Conclusion and other useful LLVM tidbits -====================================================== +====================================== +Kaleidoscope: Adding Debug Information +====================================== .. contents:: :local: -Tutorial Conclusion -=================== - -Welcome to the final chapter of the "`Implementing a language with -LLVM `_" tutorial. In the course of this tutorial, we have -grown our little Kaleidoscope language from being a useless toy, to -being a semi-interesting (but probably still useless) toy. :) - -It is interesting to see how far we've come, and how little code it has -taken. We built the entire lexer, parser, AST, code generator, and an -interactive run-loop (with a JIT!) by-hand in under 700 lines of -(non-comment/non-blank) code. - -Our little language supports a couple of interesting features: it -supports user defined binary and unary operators, it uses JIT -compilation for immediate evaluation, and it supports a few control flow -constructs with SSA construction. - -Part of the idea of this tutorial was to show you how easy and fun it -can be to define, build, and play with languages. Building a compiler -need not be a scary or mystical process! Now that you've seen some of -the basics, I strongly encourage you to take the code and hack on it. -For example, try adding: - -- **global variables** - While global variables have questional value - in modern software engineering, they are often useful when putting - together quick little hacks like the Kaleidoscope compiler itself. - Fortunately, our current setup makes it very easy to add global - variables: just have value lookup check to see if an unresolved - variable is in the global variable symbol table before rejecting it. - To create a new global variable, make an instance of the LLVM - ``GlobalVariable`` class. -- **typed variables** - Kaleidoscope currently only supports variables - of type double. This gives the language a very nice elegance, because - only supporting one type means that you never have to specify types. - Different languages have different ways of handling this. The easiest - way is to require the user to specify types for every variable - definition, and record the type of the variable in the symbol table - along with its Value\*. -- **arrays, structs, vectors, etc** - Once you add types, you can start - extending the type system in all sorts of interesting ways. Simple - arrays are very easy and are quite useful for many different - applications. Adding them is mostly an exercise in learning how the - LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction - works: it is so nifty/unconventional, it `has its own - FAQ <../GetElementPtr.html>`_! If you add support for recursive types - (e.g. linked lists), make sure to read the `section in the LLVM - Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that - describes how to construct them. -- **standard runtime** - Our current language allows the user to access - arbitrary external functions, and we use it for things like "printd" - and "putchard". As you extend the language to add higher-level - constructs, often these constructs make the most sense if they are - lowered to calls into a language-supplied runtime. For example, if - you add hash tables to the language, it would probably make sense to - add the routines to a runtime, instead of inlining them all the way. -- **memory management** - Currently we can only access the stack in - Kaleidoscope. It would also be useful to be able to allocate heap - memory, either with calls to the standard libc malloc/free interface - or with a garbage collector. If you would like to use garbage - collection, note that LLVM fully supports `Accurate Garbage - Collection <../GarbageCollection.html>`_ including algorithms that - move objects and need to scan/update the stack. -- **debugger support** - LLVM supports generation of `DWARF Debug - info <../SourceLevelDebugging.html>`_ which is understood by common - debuggers like GDB. Adding support for debug info is fairly - straightforward. The best way to understand it is to compile some - C/C++ code with "``clang -g -O0``" and taking a look at what it - produces. -- **exception handling support** - LLVM supports generation of `zero - cost exceptions <../ExceptionHandling.html>`_ which interoperate with - code compiled in other languages. You could also generate code by - implicitly making every function return an error value and checking - it. You could also make explicit use of setjmp/longjmp. There are - many different ways to go here. -- **object orientation, generics, database access, complex numbers, - geometric programming, ...** - Really, there is no end of crazy - features that you can add to the language. -- **unusual domains** - We've been talking about applying LLVM to a - domain that many people are interested in: building a compiler for a - specific language. However, there are many other domains that can use - compiler technology that are not typically considered. For example, - LLVM has been used to implement OpenGL graphics acceleration, - translate C++ code to ActionScript, and many other cute and clever - things. Maybe you will be the first to JIT compile a regular - expression interpreter into native code with LLVM? - -Have fun - try doing something crazy and unusual. Building a language -like everyone else always has, is much less fun than trying something a -little crazy or off the wall and seeing how it turns out. If you get -stuck or want to talk about it, feel free to email the `llvmdev mailing -list `_: it has lots -of people who are interested in languages and are often willing to help -out. - -Before we end this tutorial, I want to talk about some "tips and tricks" -for generating LLVM IR. These are some of the more subtle things that -may not be obvious, but are very useful if you want to take advantage of -LLVM's capabilities. - -Properties of the LLVM IR -========================= - -We have a couple common questions about code in the LLVM IR form - lets -just get these out of the way right now, shall we? - -Target Independence -------------------- - -Kaleidoscope is an example of a "portable language": any program written -in Kaleidoscope will work the same way on any target that it runs on. -Many other languages have this property, e.g. lisp, java, haskell, -javascript, python, etc (note that while these languages are portable, -not all their libraries are). - -One nice aspect of LLVM is that it is often capable of preserving target -independence in the IR: you can take the LLVM IR for a -Kaleidoscope-compiled program and run it on any target that LLVM -supports, even emitting C code and compiling that on targets that LLVM -doesn't support natively. You can trivially tell that the Kaleidoscope -compiler generates target-independent code because it never queries for -any target-specific information when generating code. - -The fact that LLVM provides a compact, target-independent, -representation for code gets a lot of people excited. Unfortunately, -these people are usually thinking about C or a language from the C -family when they are asking questions about language portability. I say -"unfortunately", because there is really no way to make (fully general) -C code portable, other than shipping the source code around (and of -course, C source code is not actually portable in general either - ever -port a really old application from 32- to 64-bits?). - -The problem with C (again, in its full generality) is that it is heavily -laden with target specific assumptions. As one simple example, the -preprocessor often destructively removes target-independence from the -code when it processes the input text: - -.. code-block:: c - - #ifdef __i386__ - int X = 1; - #else - int X = 42; - #endif - -While it is possible to engineer more and more complex solutions to -problems like this, it cannot be solved in full generality in a way that -is better than shipping the actual source code. - -That said, there are interesting subsets of C that can be made portable. -If you are willing to fix primitive types to a fixed size (say int = -32-bits, and long = 64-bits), don't care about ABI compatibility with -existing binaries, and are willing to give up some other minor features, -you can have portable code. This can make sense for specialized domains -such as an in-kernel language. - -Safety Guarantees ------------------ - -Many of the languages above are also "safe" languages: it is impossible -for a program written in Java to corrupt its address space and crash the -process (assuming the JVM has no bugs). Safety is an interesting -property that requires a combination of language design, runtime -support, and often operating system support. - -It is certainly possible to implement a safe language in LLVM, but LLVM -IR does not itself guarantee safety. The LLVM IR allows unsafe pointer -casts, use after free bugs, buffer over-runs, and a variety of other -problems. Safety needs to be implemented as a layer on top of LLVM and, -conveniently, several groups have investigated this. Ask on the `llvmdev -mailing list `_ if -you are interested in more details. - -Language-Specific Optimizations -------------------------------- - -One thing about LLVM that turns off many people is that it does not -solve all the world's problems in one system (sorry 'world hunger', -someone else will have to solve you some other day). One specific -complaint is that people perceive LLVM as being incapable of performing -high-level language-specific optimization: LLVM "loses too much -information". - -Unfortunately, this is really not the place to give you a full and -unified version of "Chris Lattner's theory of compiler design". Instead, -I'll make a few observations: - -First, you're right that LLVM does lose information. For example, as of -this writing, there is no way to distinguish in the LLVM IR whether an -SSA-value came from a C "int" or a C "long" on an ILP32 machine (other -than debug info). Both get compiled down to an 'i32' value and the -information about what it came from is lost. The more general issue -here, is that the LLVM type system uses "structural equivalence" instead -of "name equivalence". Another place this surprises people is if you -have two types in a high-level language that have the same structure -(e.g. two different structs that have a single int field): these types -will compile down into a single LLVM type and it will be impossible to -tell what it came from. - -Second, while LLVM does lose information, LLVM is not a fixed target: we -continue to enhance and improve it in many different ways. In addition -to adding new features (LLVM did not always support exceptions or debug -info), we also extend the IR to capture important information for -optimization (e.g. whether an argument is sign or zero extended, -information about pointers aliasing, etc). Many of the enhancements are -user-driven: people want LLVM to include some specific feature, so they -go ahead and extend it. - -Third, it is *possible and easy* to add language-specific optimizations, -and you have a number of choices in how to do it. As one trivial -example, it is easy to add language-specific optimization passes that -"know" things about code compiled for a language. In the case of the C -family, there is an optimization pass that "knows" about the standard C -library functions. If you call "exit(0)" in main(), it knows that it is -safe to optimize that into "return 0;" because C specifies what the -'exit' function does. - -In addition to simple library knowledge, it is possible to embed a -variety of other language-specific information into the LLVM IR. If you -have a specific need and run into a wall, please bring the topic up on -the llvmdev list. At the very worst, you can always treat LLVM as if it -were a "dumb code generator" and implement the high-level optimizations -you desire in your front-end, on the language-specific AST. - -Tips and Tricks -=============== - -There is a variety of useful tips and tricks that you come to know after -working on/with LLVM that aren't obvious at first glance. Instead of -letting everyone rediscover them, this section talks about some of these -issues. - -Implementing portable offsetof/sizeof -------------------------------------- - -One interesting thing that comes up, if you are trying to keep the code -generated by your compiler "target independent", is that you often need -to know the size of some LLVM type or the offset of some field in an -llvm structure. For example, you might need to pass the size of a type -into a function that allocates memory. - -Unfortunately, this can vary widely across targets: for example the -width of a pointer is trivially target-specific. However, there is a -`clever way to use the getelementptr -instruction `_ -that allows you to compute this in a portable way. - -Garbage Collected Stack Frames ------------------------------- - -Some languages want to explicitly manage their stack frames, often so -that they are garbage collected or to allow easy implementation of -closures. There are often better ways to implement these features than -explicit stack frames, but `LLVM does support -them, `_ -if you want. It requires your front-end to convert the code into -`Continuation Passing -Style `_ and -the use of tail calls (which LLVM also supports). +Chapter 8 Introduction +====================== + +Welcome to Chapter 8 of the "`Implementing a language with +LLVM `_" tutorial. In chapters 1 through 7, we've built a +decent little programming language with functions and variables. +What happens if something goes wrong though, how do you debug your +program? + +Source level debugging uses formatted data that helps a debugger +translate from binary and the state of the machine back to the +source that the programmer wrote. In LLVM we generally use a format +called `DWARF `_. DWARF is a compact encoding +that represents types, source locations, and variable locations. + +The short summary of this chapter is that we'll go through the +various things you have to add to a programming language to +support debug info, and how you translate that into DWARF. + +Caveat: For now we can't debug via the JIT, so we'll need to compile +our program down to something small and standalone. As part of this +we'll make a few modifications to the running of the language and +how programs are compiled. This means that we'll have a source file +with a simple program written in Kaleidoscope rather than the +interactive JIT. It does involve a limitation that we can only +have one "top level" command at a time to reduce the number of +changes necessary. + +Here's the sample program we'll be compiling: + +.. code-block:: python + + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2); + + fib(10) + + +Why is this a hard problem? +=========================== + +Debug information is a hard problem for a few different reasons - mostly +centered around optimized code. First, optimization makes keeping source +locations more difficult. In LLVM IR we keep the original source location +for each IR level instruction on the instruction. Optimization passes +should keep the source locations for newly created instructions, but merged +instructions only get to keep a single location - this can cause jumping +around when stepping through optimized programs. Secondly, optimization +can move variables in ways that are either optimized out, shared in memory +with other variables, or difficult to track. For the purposes of this +tutorial we're going to avoid optimization (as you'll see with one of the +next sets of patches). + +Ahead-of-Time Compilation Mode +============================== + +To highlight only the aspects of adding debug information to a source +language without needing to worry about the complexities of JIT debugging +we're going to make a few changes to Kaleidoscope to support compiling +the IR emitted by the front end into a simple standalone program that +you can execute, debug, and see results. + +First we make our anonymous function that contains our top level +statement be our "main": + +.. code-block:: udiff + + - PrototypeAST *Proto = new PrototypeAST("", std::vector()); + + PrototypeAST *Proto = new PrototypeAST("main", std::vector()); + +just with the simple change of giving it a name. + +Then we're going to remove the command line code wherever it exists: + +.. code-block:: udiff + + @@ -1129,7 +1129,6 @@ static void HandleTopLevelExpression() { + /// top ::= definition | external | expression | ';' + static void MainLoop() { + while (1) { + - fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + @@ -1184,7 +1183,6 @@ int main() { + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + - fprintf(stderr, "ready> "); + getNextToken(); + +Lastly we're going to disable all of the optimization passes and the JIT so +that the only thing that happens after we're done parsing and generating +code is that the llvm IR goes to standard error: + +.. code-block:: udiff + + @@ -1108,17 +1108,8 @@ static void HandleExtern() { + static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + - if (Function *LF = F->Codegen()) { + - // We're just doing this to make sure it executes. + - TheExecutionEngine->finalizeObject(); + - // 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; + - // Ignore the return value for this. + - (void)FP; + + if (!F->Codegen()) { + + fprintf(stderr, "Error generating code for top level expr"); + } + } else { + // Skip token for error recovery. + @@ -1439,11 +1459,11 @@ int main() { + // target lays out data structures. + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); + OurFPM.add(new DataLayoutPass()); + +#if 0 + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + @@ -1218,7 +1210,7 @@ int main() { + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + - + + #endif + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + +This relatively small set of changes get us to the point that we can compile +our piece of Kaleidoscope language down to an executable program via this +command line: + +.. code-block:: bash + + Kaleidoscope-Ch8 < fib.ks | & clang -x ir - + +which gives an a.out/a.exe in the current working directory. + +Compile Unit +============ + +The top level container for a section of code in DWARF is a compile unit. +This contains the type and function data for an individual translation unit +(read: one file of source code). So the first thing we need to do is +construct one for our fib.ks file. + +DWARF Emission Setup +==================== + +Similar to the ``IRBuilder`` class we have a +```DIBuilder`` `_ class +that helps in constructing debug metadata for an llvm IR file. It +corresponds 1:1 similarly to ``IRBuilder`` and llvm IR, but with nicer names. +Using it does require that you be more familiar with DWARF terminology than +you needed to be with ``IRBuilder`` and ``Instruction`` names, but if you +read through the general documentation on the +```Metadata Format`` `_ it +should be a little more clear. We'll be using this class to construct all +of our IR level descriptions. Construction for it takes a module so we +need to construct it shortly after we construct our module. We've left it +as a global static variable to make it a bit easier to use. + +Next we're going to create a small container to cache some of our frequent +data. The first will be our compile unit, but we'll also write a bit of +code for our one type since we won't have to worry about multiple typed +expressions: + +.. code-block:: c++ + + static DIBuilder *DBuilder; + + struct DebugInfo { + DICompileUnit TheCU; + DIType DblTy; + + DIType getDoubleTy(); + } KSDbgInfo; + + DIType DebugInfo::getDoubleTy() { + if (DblTy.isValid()) + return DblTy; + + DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float); + return DblTy; + } + +And then later on in ``main`` when we're constructing our module: + +.. code-block:: c++ + + DBuilder = new DIBuilder(*TheModule); + + KSDbgInfo.TheCU = DBuilder->createCompileUnit( + dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0); + +There are a couple of things to note here. First, while we're producing a +compile unit for a language called Kaleidoscope we used the language +constant for C. This is because a debugger wouldn't necessarily understand +the calling conventions or default ABI for a language it doesn't recognize +and we follow the C ABI in our llvm code generation so it's the closest +thing to accurate. This ensures we can actually call functions from the +debugger and have them execute. Secondly, you'll see the "fib.ks" in the +call to ``createCompileUnit``. This is a default hard coded value since +we're using shell redirection to put our source into the Kaleidoscope +compiler. In a usual front end you'd have an input file name and it would +go there. + +One last thing as part of emitting debug information via DIBuilder is that +we need to "finalize" the debug information. The reasons are part of the +underlying API for DIBuilder, but make sure you do this near the end of +main: + +.. code-block:: c++ + + DBuilder->finalize(); + +before you dump out the module. + +Functions +========= + +Now that we have our ``Compile Unit`` and our source locations, we can add +function definitions to the debug info. So in ``PrototypeAST::Codegen`` we +add a few lines of code to describe a context for our subprogram, in this +case the "File", and the actual definition of the function itself. + +So the context: + +.. code-block:: c++ + + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + +giving us a DIFile and asking the ``Compile Unit`` we created above for the +directory and filename where we are currently. Then, for now, we use some +source locations of 0 (since our AST doesn't currently have source location +information) and construct our function definition: + +.. code-block:: c++ + + DIDescriptor FContext(Unit); + unsigned LineNo = 0; + unsigned ScopeLine = 0; + DISubprogram SP = DBuilder->createFunction( + FContext, Name, StringRef(), Unit, LineNo, + CreateFunctionType(Args.size(), Unit), false /* internal linkage */, + true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + +and we now have a DISubprogram that contains a reference to all of our metadata +for the function. + +Source Locations +================ + +The most important thing for debug information is accurate source location - +this makes it possible to map your source code back. We have a problem though, +Kaleidoscope really doesn't have any source location information in the lexer +or parser so we'll need to add it. + +.. code-block:: c++ + + struct SourceLocation { + int Line; + int Col; + }; + static SourceLocation CurLoc; + static SourceLocation LexLoc = {1, 0}; + + static int advance() { + int LastChar = getchar(); + + if (LastChar == '\n' || LastChar == '\r') { + LexLoc.Line++; + LexLoc.Col = 0; + } else + LexLoc.Col++; + return LastChar; + } + +In this set of code we've added some functionality on how to keep track of the +line and column of the "source file". As we lex every token we set our current +current "lexical location" to the assorted line and column for the beginning +of the token. We do this by overriding all of the previous calls to +``getchar()`` with our new ``advance()`` that keeps track of the information +and then we have added to all of our AST classes a source location: + +.. code-block:: c++ + + class ExprAST { + SourceLocation Loc; + + public: + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } + +that we pass down through when we create a new expression: + +.. code-block:: c++ + + LHS = new BinaryExprAST(BinLoc, BinOp, LHS, RHS); + +giving us locations for each of our expressions and variables. + +From this we can make sure to tell ``DIBuilder`` when we're at a new source +location so it can use that when we generate the rest of our code and make +sure that each instruction has source location information. We do this +by constructing another small function: + +.. code-block:: c++ + + void DebugInfo::emitLocation(ExprAST *AST) { + DIScope *Scope; + if (LexicalBlocks.empty()) + Scope = &TheCU; + else + Scope = LexicalBlocks.back(); + Builder.SetCurrentDebugLocation( + DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); + } + +that both tells the main ``IRBuilder`` where we are, but also what scope +we're in. Since we've just created a function above we can either be in +the main file scope (like when we created our function), or now we can be +in the function scope we just created. To represent this we create a stack +of scopes: + +.. code-block:: c++ + + std::vector LexicalBlocks; + std::map FnScopeMap; + +and keep a map of each function to the scope that it represents (a DISubprogram +is also a DIScope). + +Then we make sure to: + +.. code-block:: c++ + + KSDbgInfo.emitLocation(this); + +emit the location every time we start to generate code for a new AST, and +also: + +.. code-block:: c++ + + KSDbgInfo.FnScopeMap[this] = SP; + +store the scope (function) when we create it and use it: + + KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + +when we start generating the code for each function. + +also, don't forget to pop the scope back off of your scope stack at the +end of the code generation for the function: + +.. code-block:: c++ + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + +Variables +========= + +Now that we have functions, we need to be able to print out the variables +we have in scope. Let's get our function arguments set up so we can get +decent backtraces and see how our functions are being called. It isn't +a lot of code, and we generally handle it when we're creating the +argument allocas in ``PrototypeAST::CreateArgumentAllocas``. + +.. code-block:: c++ + + DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, + *Scope, Args[Idx], Unit, Line, + KSDbgInfo.getDoubleTy(), Idx); + + Instruction *Call = DBuilder->insertDeclare( + Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); + Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + +Here we're doing a few things. First, we're grabbing our current scope +for the variable so we can say what range of code our variable is valid +through. Second, we're creating the variable, giving it the scope, +the name, source location, type, and since it's an argument, the argument +index. Third, we create an ``lvm.dbg.declare`` call to indicate at the IR +level that we've got a variable in an alloca (and it gives a starting +location for the variable). Lastly, we set a source location for the +beginning of the scope on the declare. + +One interesting thing to note at this point is that various debuggers have +assumptions based on how code and debug information was generated for them +in the past. In this case we need to do a little bit of a hack to avoid +generating line information for the function prologue so that the debugger +knows to skip over those instructions when setting a breakpoint. So in +``FunctionAST::CodeGen`` we add a couple of lines: + +.. code-block:: c++ + + // Unset the location for the prologue emission (leading instructions with no + // location in a function are considered part of the prologue and the debugger + // will run past them when breaking on a function) + KSDbgInfo.emitLocation(nullptr); + +and then emit a new location when we actually start generating code for the +body of the function: + +.. code-block:: c++ + + KSDbgInfo.emitLocation(Body); + +With this we have enough debug information to set breakpoints in functions, +print out argument variables, and call functions. Not too bad for just a +few simple lines of code! + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +debug information. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy + # Run + ./toy + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter8/toy.cpp + :language: c++ + +`Next: Conclusion and other useful LLVM tidbits `_ diff --git a/docs/tutorial/LangImpl9.rst b/docs/tutorial/LangImpl9.rst new file mode 100644 index 0000000..3398768 --- /dev/null +++ b/docs/tutorial/LangImpl9.rst @@ -0,0 +1,262 @@ +====================================================== +Kaleidoscope: Conclusion and other useful LLVM tidbits +====================================================== + +.. contents:: + :local: + +Tutorial Conclusion +=================== + +Welcome to the final chapter of the "`Implementing a language with +LLVM `_" tutorial. In the course of this tutorial, we have +grown our little Kaleidoscope language from being a useless toy, to +being a semi-interesting (but probably still useless) toy. :) + +It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, an +interactive run-loop (with a JIT!), and emitted debug information in +standalone executables - all in under 1000 lines of (non-comment/non-blank) +code. + +Our little language supports a couple of interesting features: it +supports user defined binary and unary operators, it uses JIT +compilation for immediate evaluation, and it supports a few control flow +constructs with SSA construction. + +Part of the idea of this tutorial was to show you how easy and fun it +can be to define, build, and play with languages. Building a compiler +need not be a scary or mystical process! Now that you've seen some of +the basics, I strongly encourage you to take the code and hack on it. +For example, try adding: + +- **global variables** - While global variables have questional value + in modern software engineering, they are often useful when putting + together quick little hacks like the Kaleidoscope compiler itself. + Fortunately, our current setup makes it very easy to add global + variables: just have value lookup check to see if an unresolved + variable is in the global variable symbol table before rejecting it. + To create a new global variable, make an instance of the LLVM + ``GlobalVariable`` class. +- **typed variables** - Kaleidoscope currently only supports variables + of type double. This gives the language a very nice elegance, because + only supporting one type means that you never have to specify types. + Different languages have different ways of handling this. The easiest + way is to require the user to specify types for every variable + definition, and record the type of the variable in the symbol table + along with its Value\*. +- **arrays, structs, vectors, etc** - Once you add types, you can start + extending the type system in all sorts of interesting ways. Simple + arrays are very easy and are quite useful for many different + applications. Adding them is mostly an exercise in learning how the + LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction + works: it is so nifty/unconventional, it `has its own + FAQ <../GetElementPtr.html>`_! If you add support for recursive types + (e.g. linked lists), make sure to read the `section in the LLVM + Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that + describes how to construct them. +- **standard runtime** - Our current language allows the user to access + arbitrary external functions, and we use it for things like "printd" + and "putchard". As you extend the language to add higher-level + constructs, often these constructs make the most sense if they are + lowered to calls into a language-supplied runtime. For example, if + you add hash tables to the language, it would probably make sense to + add the routines to a runtime, instead of inlining them all the way. +- **memory management** - Currently we can only access the stack in + Kaleidoscope. It would also be useful to be able to allocate heap + memory, either with calls to the standard libc malloc/free interface + or with a garbage collector. If you would like to use garbage + collection, note that LLVM fully supports `Accurate Garbage + Collection <../GarbageCollection.html>`_ including algorithms that + move objects and need to scan/update the stack. +- **exception handling support** - LLVM supports generation of `zero + cost exceptions <../ExceptionHandling.html>`_ which interoperate with + code compiled in other languages. You could also generate code by + implicitly making every function return an error value and checking + it. You could also make explicit use of setjmp/longjmp. There are + many different ways to go here. +- **object orientation, generics, database access, complex numbers, + geometric programming, ...** - Really, there is no end of crazy + features that you can add to the language. +- **unusual domains** - We've been talking about applying LLVM to a + domain that many people are interested in: building a compiler for a + specific language. However, there are many other domains that can use + compiler technology that are not typically considered. For example, + LLVM has been used to implement OpenGL graphics acceleration, + translate C++ code to ActionScript, and many other cute and clever + things. Maybe you will be the first to JIT compile a regular + expression interpreter into native code with LLVM? + +Have fun - try doing something crazy and unusual. Building a language +like everyone else always has, is much less fun than trying something a +little crazy or off the wall and seeing how it turns out. If you get +stuck or want to talk about it, feel free to email the `llvmdev mailing +list `_: it has lots +of people who are interested in languages and are often willing to help +out. + +Before we end this tutorial, I want to talk about some "tips and tricks" +for generating LLVM IR. These are some of the more subtle things that +may not be obvious, but are very useful if you want to take advantage of +LLVM's capabilities. + +Properties of the LLVM IR +========================= + +We have a couple common questions about code in the LLVM IR form - lets +just get these out of the way right now, shall we? + +Target Independence +------------------- + +Kaleidoscope is an example of a "portable language": any program written +in Kaleidoscope will work the same way on any target that it runs on. +Many other languages have this property, e.g. lisp, java, haskell, +javascript, python, etc (note that while these languages are portable, +not all their libraries are). + +One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a +Kaleidoscope-compiled program and run it on any target that LLVM +supports, even emitting C code and compiling that on targets that LLVM +doesn't support natively. You can trivially tell that the Kaleidoscope +compiler generates target-independent code because it never queries for +any target-specific information when generating code. + +The fact that LLVM provides a compact, target-independent, +representation for code gets a lot of people excited. Unfortunately, +these people are usually thinking about C or a language from the C +family when they are asking questions about language portability. I say +"unfortunately", because there is really no way to make (fully general) +C code portable, other than shipping the source code around (and of +course, C source code is not actually portable in general either - ever +port a really old application from 32- to 64-bits?). + +The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the +preprocessor often destructively removes target-independence from the +code when it processes the input text: + +.. code-block:: c + + #ifdef __i386__ + int X = 1; + #else + int X = 42; + #endif + +While it is possible to engineer more and more complex solutions to +problems like this, it cannot be solved in full generality in a way that +is better than shipping the actual source code. + +That said, there are interesting subsets of C that can be made portable. +If you are willing to fix primitive types to a fixed size (say int = +32-bits, and long = 64-bits), don't care about ABI compatibility with +existing binaries, and are willing to give up some other minor features, +you can have portable code. This can make sense for specialized domains +such as an in-kernel language. + +Safety Guarantees +----------------- + +Many of the languages above are also "safe" languages: it is impossible +for a program written in Java to corrupt its address space and crash the +process (assuming the JVM has no bugs). Safety is an interesting +property that requires a combination of language design, runtime +support, and often operating system support. + +It is certainly possible to implement a safe language in LLVM, but LLVM +IR does not itself guarantee safety. The LLVM IR allows unsafe pointer +casts, use after free bugs, buffer over-runs, and a variety of other +problems. Safety needs to be implemented as a layer on top of LLVM and, +conveniently, several groups have investigated this. Ask on the `llvmdev +mailing list `_ if +you are interested in more details. + +Language-Specific Optimizations +------------------------------- + +One thing about LLVM that turns off many people is that it does not +solve all the world's problems in one system (sorry 'world hunger', +someone else will have to solve you some other day). One specific +complaint is that people perceive LLVM as being incapable of performing +high-level language-specific optimization: LLVM "loses too much +information". + +Unfortunately, this is really not the place to give you a full and +unified version of "Chris Lattner's theory of compiler design". Instead, +I'll make a few observations: + +First, you're right that LLVM does lose information. For example, as of +this writing, there is no way to distinguish in the LLVM IR whether an +SSA-value came from a C "int" or a C "long" on an ILP32 machine (other +than debug info). Both get compiled down to an 'i32' value and the +information about what it came from is lost. The more general issue +here, is that the LLVM type system uses "structural equivalence" instead +of "name equivalence". Another place this surprises people is if you +have two types in a high-level language that have the same structure +(e.g. two different structs that have a single int field): these types +will compile down into a single LLVM type and it will be impossible to +tell what it came from. + +Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition +to adding new features (LLVM did not always support exceptions or debug +info), we also extend the IR to capture important information for +optimization (e.g. whether an argument is sign or zero extended, +information about pointers aliasing, etc). Many of the enhancements are +user-driven: people want LLVM to include some specific feature, so they +go ahead and extend it. + +Third, it is *possible and easy* to add language-specific optimizations, +and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C +family, there is an optimization pass that "knows" about the standard C +library functions. If you call "exit(0)" in main(), it knows that it is +safe to optimize that into "return 0;" because C specifies what the +'exit' function does. + +In addition to simple library knowledge, it is possible to embed a +variety of other language-specific information into the LLVM IR. If you +have a specific need and run into a wall, please bring the topic up on +the llvmdev list. At the very worst, you can always treat LLVM as if it +were a "dumb code generator" and implement the high-level optimizations +you desire in your front-end, on the language-specific AST. + +Tips and Tricks +=============== + +There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of +letting everyone rediscover them, this section talks about some of these +issues. + +Implementing portable offsetof/sizeof +------------------------------------- + +One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need +to know the size of some LLVM type or the offset of some field in an +llvm structure. For example, you might need to pass the size of a type +into a function that allocates memory. + +Unfortunately, this can vary widely across targets: for example the +width of a pointer is trivially target-specific. However, there is a +`clever way to use the getelementptr +instruction `_ +that allows you to compute this in a portable way. + +Garbage Collected Stack Frames +------------------------------ + +Some languages want to explicitly manage their stack frames, often so +that they are garbage collected or to allow easy implementation of +closures. There are often better ways to implement these features than +explicit stack frames, but `LLVM does support +them, `_ +if you want. It requires your front-end to convert the code into +`Continuation Passing +Style `_ and +the use of tail calls (which LLVM also supports). + diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index 17076fa..317a326 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -56,8 +56,8 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetOptions.h" @@ -1122,14 +1122,11 @@ static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context, /// @param numExceptionsToCatch length of exceptionTypesToCatch array /// @param exceptionTypesToCatch array of type info types to "catch" /// @returns generated function -static -llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - llvm::Function &toInvoke, - std::string ourId, - unsigned numExceptionsToCatch, - unsigned exceptionTypesToCatch[]) { +static llvm::Function *createCatchWrappedInvokeFunction( + llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, llvm::Function &toInvoke, + std::string ourId, unsigned numExceptionsToCatch, + unsigned exceptionTypesToCatch[]) { llvm::LLVMContext &context = module.getContext(); llvm::Function *toPrint32Int = module.getFunction("print32Int"); @@ -1389,13 +1386,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, /// @param nativeThrowFunct function which will throw a foreign exception /// if the above nativeThrowType matches generated function's arg. /// @returns generated function -static -llvm::Function *createThrowExceptionFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - std::string ourId, - int32_t nativeThrowType, - llvm::Function &nativeThrowFunct) { +static llvm::Function * +createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, + std::string ourId, int32_t nativeThrowType, + llvm::Function &nativeThrowFunct) { llvm::LLVMContext &context = module.getContext(); namedValues.clear(); ArgTypes unwindArgTypes; @@ -1508,10 +1503,10 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, /// @param nativeThrowFunctName name of external function which will throw /// a foreign exception /// @returns outermost generated test function. -llvm::Function *createUnwindExceptionTest(llvm::Module &module, - llvm::IRBuilder<> &builder, - llvm::FunctionPassManager &fpm, - std::string nativeThrowFunctName) { +llvm::Function * +createUnwindExceptionTest(llvm::Module &module, llvm::IRBuilder<> &builder, + llvm::legacy::FunctionPassManager &fpm, + std::string nativeThrowFunctName) { // Number of type infos to generate unsigned numTypeInfos = 6; @@ -1961,17 +1956,17 @@ int main(int argc, char *argv[]) { llvm::make_unique("my cool jit", context); llvm::Module *module = Owner.get(); - llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); + std::unique_ptr MemMgr(new llvm::SectionMemoryManager()); // Build engine with JIT llvm::EngineBuilder factory(std::move(Owner)); factory.setEngineKind(llvm::EngineKind::JIT); factory.setTargetOptions(Opts); - factory.setMCJITMemoryManager(MemMgr); + factory.setMCJITMemoryManager(std::move(MemMgr)); llvm::ExecutionEngine *executionEngine = factory.create(); { - llvm::FunctionPassManager fpm(module); + llvm::legacy::FunctionPassManager fpm(module); // Set up the optimizer pipeline. // Start with registering info about how the diff --git a/examples/Kaleidoscope/CMakeLists.txt b/examples/Kaleidoscope/CMakeLists.txt index 8c87ac5..32664aa 100644 --- a/examples/Kaleidoscope/CMakeLists.txt +++ b/examples/Kaleidoscope/CMakeLists.txt @@ -1,6 +1,16 @@ +add_custom_target(Kaleidoscope) +set_target_properties(Kaleidoscope PROPERTIES FOLDER Examples) + +macro(add_kaleidoscope_chapter name) + add_dependencies(Kaleidoscope ${name}) + add_llvm_example(${name} ${ARGN}) +endmacro(add_kaleidoscope_chapter name) + add_subdirectory(Chapter2) add_subdirectory(Chapter3) add_subdirectory(Chapter4) add_subdirectory(Chapter5) add_subdirectory(Chapter6) add_subdirectory(Chapter7) +add_subdirectory(Chapter8) +add_subdirectory(Orc) diff --git a/examples/Kaleidoscope/Chapter2/CMakeLists.txt b/examples/Kaleidoscope/Chapter2/CMakeLists.txt index 79f2b17..fed3f4b 100644 --- a/examples/Kaleidoscope/Chapter2/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter2/CMakeLists.txt @@ -1,3 +1,3 @@ -add_llvm_example(Kaleidoscope-Ch2 +add_kaleidoscope_chapter(Kaleidoscope-Ch2 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter3/CMakeLists.txt b/examples/Kaleidoscope/Chapter3/CMakeLists.txt index a98d7df..8053c96 100644 --- a/examples/Kaleidoscope/Chapter3/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter3/CMakeLists.txt @@ -3,6 +3,6 @@ set(LLVM_LINK_COMPONENTS Support ) -add_llvm_example(Kaleidoscope-Ch3 +add_kaleidoscope_chapter(Kaleidoscope-Ch3 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/examples/Kaleidoscope/Chapter4/CMakeLists.txt index 2f828dc..2c01e12 100644 --- a/examples/Kaleidoscope/Chapter4/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -3,12 +3,14 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT + RuntimeDyld ScalarOpts Support - nativecodegen + TransformUtils + native ) -add_llvm_example(Kaleidoscope-Ch4 +add_kaleidoscope_chapter(Kaleidoscope-Ch4 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index 3564d75..70fe57f 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.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/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -26,14 +28,16 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5 + tok_identifier = -4, + tok_number = -5 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +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() { @@ -48,12 +52,14 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -66,13 +72,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + 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; @@ -97,6 +104,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -105,6 +113,7 @@ public: /// 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(); @@ -114,19 +123,21 @@ public: 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) + : 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; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; @@ -136,10 +147,11 @@ public: class PrototypeAST { std::string Name; std::vector Args; + public: PrototypeAST(const std::string &name, const std::vector &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -147,10 +159,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -163,9 +175,7 @@ public: /// 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(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -175,17 +185,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + 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; } +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(); @@ -194,22 +214,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -219,7 +241,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -232,13 +254,14 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } @@ -248,10 +271,14 @@ static ExprAST *ParseParenExpr() { /// ::= 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(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); } } @@ -261,28 +288,30 @@ 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 - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + 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; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -293,8 +322,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -306,27 +336,28 @@ static PrototypeAST *ParsePrototype() { 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 ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -345,20 +376,258 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + 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 *getSymbolAddress(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 &) = delete; + void operator=(const HelpingMemoryManager &) = delete; + +public: + HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} + virtual ~HelpingMemoryManager() {} + + /// This method returns the address of the specified symbol. + /// Our implementation will attempt to find symbols in other + /// modules associated with the MCJITHelper to cross link symbols + /// from one generated module to another. + virtual uint64_t getSymbolAddress(const std::string &Name) override; + +private: + MCJITHelper *MasterHelper; +}; + +uint64_t HelpingMemoryManager::getSymbolAddress(const std::string &Name) { + uint64_t FnAddr = SectionMemoryManager::getSymbolAddress(Name); + if (FnAddr) + return FnAddr; + + uint64_t HelperFun = (uint64_t)MasterHelper->getSymbolAddress(Name); + if (!HelperFun) + report_fatal_error("Program used extern function '" + Name + + "' which could not be resolved!"); + + return HelperFun; +} + +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(std::unique_ptr(OpenModule)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(std::unique_ptr( + 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 + auto *FPM = new legacy::FunctionPassManager(OpenModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OpenModule->setDataLayout(NewEngine->getDataLayout()); + FPM->add(new DataLayoutPass()); + // 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::getSymbolAddress(const std::string &Name) { + // Look for the symbol 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) { + uint64_t FAddr = (*it)->getFunctionAddress(Name); + if (FAddr) { + return (void *)FAddr; + } + } + 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 Module *TheModule; +static MCJITHelper *JITHelper; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; -static FunctionPassManager *TheFPM; +static std::map NamedValues; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -373,93 +642,102 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + 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.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"); + default: + return ErrorV("invalid binary operator"); } } Value *CallExprAST::Codegen() { // Look up the name in the global module table. - Function *CalleeF = TheModule->getFunction(Callee); + Function *CalleeF = JITHelper->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; + 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; + 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); - + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + std::string FnName = MakeLegalFunctionName(Name); + + Module *M = JITHelper->getModuleForNewFunction(); + + Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. - if (F->getName() != Name) { + if (F->getName() != FnName) { // Delete the one we just made and get the existing one. F->eraseFromParent(); - F = TheModule->getFunction(Name); - + F = JITHelper->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); @@ -467,12 +745,9 @@ Function *FunctionAST::Codegen() { // 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; @@ -482,8 +757,6 @@ Function *FunctionAST::Codegen() { // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// -static ExecutionEngine *TheExecutionEngine; - static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { if (Function *LF = F->Codegen()) { @@ -513,8 +786,8 @@ static void HandleTopLevelExpression() { if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { // JIT the function, returning a function pointer. - void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + void *FPtr = JITHelper->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; @@ -531,11 +804,20 @@ 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; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -545,8 +827,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -557,61 +838,27 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); + JITHelper = new MCJITHelper(Context); // Install standard binary operators. // 1 is lowest precedence. BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); - // Make the module, which holds all the code. - std::unique_ptr Owner = make_unique("my cool jit", Context); - TheModule = Owner.get(); - - // Create the JIT. This takes ownership of the module. - std::string ErrStr; - TheExecutionEngine = - EngineBuilder(std::move(Owner)).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. - TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass()); - // 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(); + JITHelper->dump(); return 0; } diff --git a/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/examples/Kaleidoscope/Chapter5/CMakeLists.txt index 1912ddc..aac9949 100644 --- a/examples/Kaleidoscope/Chapter5/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -3,12 +3,12 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support - nativecodegen + native ) -add_llvm_example(Kaleidoscope-Ch5 +add_kaleidoscope_chapter(Kaleidoscope-Ch5 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index 4929a20..728a2f5 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.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/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -26,18 +28,23 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10 + 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 +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() { @@ -52,17 +59,24 @@ static int gettok() { 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 == "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.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -75,13 +89,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + 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; @@ -106,6 +121,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -114,6 +130,7 @@ public: /// 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(); @@ -123,28 +140,31 @@ public: 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) + : 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; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + 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) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -152,10 +172,11 @@ public: 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) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -165,10 +186,11 @@ public: class PrototypeAST { std::string Name; std::vector Args; + public: PrototypeAST(const std::string &name, const std::vector &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -176,10 +198,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -192,9 +214,7 @@ public: /// 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(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -204,17 +224,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + 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; } +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(); @@ -223,22 +253,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -248,7 +280,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -261,80 +293,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + 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. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -347,12 +386,18 @@ static ExprAST *ParseForExpr() { /// ::= 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(); + 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(); } } @@ -362,28 +407,30 @@ 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 - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + 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; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -394,8 +441,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -407,27 +455,28 @@ static PrototypeAST *ParsePrototype() { 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 ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -446,7 +495,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -456,10 +505,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; -static FunctionPassManager *TheFPM; +static std::map NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -474,18 +526,23 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + 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.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"); + default: + return ErrorV("invalid binary operator"); } } @@ -494,66 +551,70 @@ Value *CallExprAST::Codegen() { 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; + 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; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + 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"); - + 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 *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; - + 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; - + 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"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -564,7 +625,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -575,136 +636,141 @@ Value *ForExprAST::Codegen() { // 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; - + 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); - + 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()); + 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; + 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; - + 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"); - + 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); - + 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); - + 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); @@ -714,10 +780,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; @@ -757,9 +823,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // 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; @@ -776,11 +843,20 @@ 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; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -790,8 +866,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -802,6 +877,8 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -809,7 +886,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -822,13 +899,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/examples/Kaleidoscope/Chapter6/CMakeLists.txt index d36f030..55b9a78 100644 --- a/examples/Kaleidoscope/Chapter6/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -3,12 +3,12 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support - nativecodegen + native ) -add_llvm_example(Kaleidoscope-Ch6 +add_kaleidoscope_chapter(Kaleidoscope-Ch6 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index 06da9ac..8131aa1 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.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/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -26,21 +28,27 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12 + tok_binary = -11, + tok_unary = -12 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +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() { @@ -55,19 +63,28 @@ static int gettok() { 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 == "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.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -80,13 +97,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + 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; @@ -111,6 +129,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -119,6 +138,7 @@ public: /// 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(); @@ -128,9 +148,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -138,28 +159,31 @@ public: 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) + : 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; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + 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) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -167,10 +191,11 @@ public: 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) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -181,22 +206,22 @@ class PrototypeAST { std::string Name; std::vector Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + 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) {} - + : 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]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); }; @@ -204,10 +229,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -220,9 +245,7 @@ public: /// 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(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -232,17 +255,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + 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; } +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(); @@ -251,22 +284,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -276,7 +311,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -289,80 +324,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + 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. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -375,12 +417,18 @@ static ExprAST *ParseForExpr() { /// ::= 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(); + 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(); } } @@ -391,7 +439,7 @@ 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(); @@ -406,28 +454,30 @@ 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 - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + 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; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -438,8 +488,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -449,10 +500,10 @@ static ExprAST *ParseExpression() { /// ::= 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"); @@ -478,7 +529,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -488,31 +539,32 @@ static PrototypeAST *ParsePrototype() { } 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 ')'. - + 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. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -531,7 +583,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -541,10 +593,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; -static FunctionPassManager *TheFPM; +static std::map NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -558,37 +613,43 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + 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; - + 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.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; + 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); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -598,66 +659,70 @@ Value *CallExprAST::Codegen() { 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; + 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; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + 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"); - + 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 *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; - + 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; - + 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"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -668,7 +733,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -679,140 +744,145 @@ Value *ForExprAST::Codegen() { // 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; - + 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); - + 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()); + 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; + 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; - + 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"); - + 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); - + 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); - + 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); @@ -822,10 +892,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -868,9 +938,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // 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; @@ -887,11 +958,20 @@ 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; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -901,15 +981,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +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) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -920,6 +998,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -927,7 +1007,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -940,13 +1020,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/examples/Kaleidoscope/Chapter7/CMakeLists.txt index bdc0e55..4bc1b2c 100644 --- a/examples/Kaleidoscope/Chapter7/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -3,15 +3,15 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - MC + MCJIT ScalarOpts Support TransformUtils - nativecodegen + native ) set(LLVM_REQUIRES_RTTI 1) -add_llvm_example(Kaleidoscope-Ch7 +add_kaleidoscope_chapter(Kaleidoscope-Ch7 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index 56a6fa9..82f083a 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1,12 +1,14 @@ #include "llvm/Analysis/Passes.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/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -26,24 +28,30 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12, - + 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 +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() { @@ -58,20 +66,30 @@ static int gettok() { 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; + 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.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -84,13 +102,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + 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; @@ -115,6 +134,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -123,6 +143,7 @@ public: /// 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; } @@ -133,9 +154,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -143,28 +165,31 @@ public: 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) + : 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; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + 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) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -172,22 +197,24 @@ public: 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) {} + : 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; + std::vector > VarNames; ExprAST *Body; + public: - VarExprAST(const std::vector > &varnames, + VarExprAST(const std::vector > &varnames, ExprAST *body) - : VarNames(varnames), Body(body) {} - + : VarNames(varnames), Body(body) {} + virtual Value *Codegen(); }; @@ -197,24 +224,24 @@ class PrototypeAST { std::string Name; std::vector Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + 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) {} - + : 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]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -222,10 +249,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -238,9 +265,7 @@ public: /// 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(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -250,17 +275,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + 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; } +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(); @@ -269,22 +304,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -294,7 +331,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -307,126 +344,136 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + 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. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { - getNextToken(); // eat the var. + getNextToken(); // eat the var. - std::vector > VarNames; + 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. + getNextToken(); // eat identifier. // Read the optional initializer. ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); - if (Init == 0) return 0; + if (Init == 0) + return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. - if (CurTok != ',') break; + 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'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; - + if (Body == 0) + return 0; + return new VarExprAST(VarNames, Body); } @@ -439,13 +486,20 @@ static ExprAST *ParseVarExpr() { /// ::= 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(); + 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(); } } @@ -456,7 +510,7 @@ 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(); @@ -471,28 +525,30 @@ 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 - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + 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; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -503,8 +559,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -514,10 +571,10 @@ static ExprAST *ParseExpression() { /// ::= 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"); @@ -543,7 +600,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -553,31 +610,32 @@ static PrototypeAST *ParsePrototype() { } 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 ')'. - + 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. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -596,7 +654,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -606,17 +664,20 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; -static FunctionPassManager *TheFPM; +static std::map NamedValues; +static legacy::FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +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()); + TheFunction->getEntryBlock().begin()); return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, VarName.c_str()); } @@ -628,7 +689,8 @@ Value *NumberExprAST::Codegen() { Value *VariableExprAST::Codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; - if (V == 0) return ErrorV("Unknown variable name"); + if (V == 0) + return ErrorV("Unknown variable name"); // Load the value. return Builder.CreateLoad(V, Name.c_str()); @@ -636,12 +698,13 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + 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"); } @@ -649,42 +712,49 @@ 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); + 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; + if (Val == 0) + return 0; // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; - if (Variable == 0) return ErrorV("Unknown variable name"); + 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; - + 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.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; + 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); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -694,66 +764,70 @@ Value *CallExprAST::Codegen() { 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; + 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; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + 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"); - + 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 *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; - + 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; - + 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"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -766,7 +840,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -779,95 +853,98 @@ Value *ForExprAST::Codegen() { // 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; - + 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); - + 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; + 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; - + 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"); - + 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); - + 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: @@ -876,26 +953,28 @@ Value *VarExprAST::Codegen() { Value *InitVal; if (Init) { InitVal = Init->Codegen(); - if (InitVal == 0) return 0; + 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; - + 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]; @@ -906,39 +985,40 @@ Value *VarExprAST::Codegen() { 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); - + 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; } @@ -960,19 +1040,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *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); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -985,10 +1065,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -1031,9 +1111,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // 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; @@ -1050,11 +1131,20 @@ 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; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -1064,15 +1154,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +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) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -1083,6 +1171,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -1091,7 +1181,7 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); @@ -1104,13 +1194,16 @@ int main() { // Create the JIT. This takes ownership of the module. std::string ErrStr; TheExecutionEngine = - EngineBuilder(std::move(Owner)).setErrorStr(&ErrStr).create(); + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } - FunctionPassManager OurFPM(TheModule); + legacy::FunctionPassManager OurFPM(TheModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. diff --git a/examples/Kaleidoscope/Chapter8/CMakeLists.txt b/examples/Kaleidoscope/Chapter8/CMakeLists.txt new file mode 100644 index 0000000..42882e9 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + MCJIT + Support + native + ) + +set(LLVM_REQUIRES_RTTI 1) + +add_kaleidoscope_chapter(Kaleidoscope-Ch8 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter8/Makefile b/examples/Kaleidoscope/Chapter8/Makefile new file mode 100644 index 0000000..8e4d422 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/Makefile @@ -0,0 +1,16 @@ +##===- examples/Kaleidoscope/Chapter7/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch8 +EXAMPLE_TOOL = 1 +REQUIRES_RTTI := 1 + +LINK_COMPONENTS := core mcjit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter8/toy.cpp b/examples/Kaleidoscope/Chapter8/toy.cpp new file mode 100644 index 0000000..30d4669 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/toy.cpp @@ -0,0 +1,1494 @@ +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#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 +}; + +std::string getTokName(int Tok) { + switch (Tok) { + case tok_eof: + return "eof"; + case tok_def: + return "def"; + case tok_extern: + return "extern"; + case tok_identifier: + return "identifier"; + case tok_number: + return "number"; + case tok_if: + return "if"; + case tok_then: + return "then"; + case tok_else: + return "else"; + case tok_for: + return "for"; + case tok_in: + return "in"; + case tok_binary: + return "binary"; + case tok_unary: + return "unary"; + case tok_var: + return "var"; + } + return std::string(1, (char)Tok); +} + +namespace { +class PrototypeAST; +class ExprAST; +} +static IRBuilder<> Builder(getGlobalContext()); +struct DebugInfo { + DICompileUnit TheCU; + DIType DblTy; + std::vector LexicalBlocks; + std::map FnScopeMap; + + void emitLocation(ExprAST *AST); + DIType getDoubleTy(); +} KSDbgInfo; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number +struct SourceLocation { + int Line; + int Col; +}; +static SourceLocation CurLoc; +static SourceLocation LexLoc = { 1, 0 }; + +static int advance() { + int LastChar = getchar(); + + if (LastChar == '\n' || LastChar == '\r') { + LexLoc.Line++; + LexLoc.Col = 0; + } else + LexLoc.Col++; + return LastChar; +} + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = advance(); + + CurLoc = LexLoc; + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = advance()))) + 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 = advance(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do + LastChar = advance(); + 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 = advance(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { + +std::ostream &indent(std::ostream &O, int size) { + return O << std::string(size, ' '); +} + +/// ExprAST - Base class for all expression nodes. +class ExprAST { + SourceLocation Loc; + +public: + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } + 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 std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Val, ind); + } + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; + +public: + VariableExprAST(SourceLocation Loc, const std::string &name) + : ExprAST(Loc), Name(name) {} + const std::string &getName() const { return Name; } + virtual std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Name, ind); + } + 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 std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "unary" << Opcode, ind); + Operand->dump(out, ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; + +public: + BinaryExprAST(SourceLocation Loc, char op, ExprAST *lhs, ExprAST *rhs) + : ExprAST(Loc), Op(op), LHS(lhs), RHS(rhs) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "binary" << Op, ind); + LHS->dump(indent(out, ind) << "LHS:", ind + 1); + RHS->dump(indent(out, ind) << "RHS:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; + +public: + CallExprAST(SourceLocation Loc, const std::string &callee, + std::vector &args) + : ExprAST(Loc), Callee(callee), Args(args) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "call " << Callee, ind); + for (ExprAST *Arg : Args) + Arg->dump(indent(out, ind + 1), ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; + +public: + IfExprAST(SourceLocation Loc, ExprAST *cond, ExprAST *then, ExprAST *_else) + : ExprAST(Loc), Cond(cond), Then(then), Else(_else) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "if", ind); + Cond->dump(indent(out, ind) << "Cond:", ind + 1); + Then->dump(indent(out, ind) << "Then:", ind + 1); + Else->dump(indent(out, ind) << "Else:", ind + 1); + return out; + } + 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 std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "for", ind); + Start->dump(indent(out, ind) << "Cond:", ind + 1); + End->dump(indent(out, ind) << "End:", ind + 1); + Step->dump(indent(out, ind) << "Step:", ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + 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 std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "var", ind); + for (const auto &NamedVar : VarNames) + NamedVar.second->dump(indent(out, ind) << NamedVar.first << ':', ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + 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. + int Line; + +public: + PrototypeAST(SourceLocation Loc, const std::string &name, + const std::vector &args, bool isoperator = false, + unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec), + Line(Loc.Line) {} + + 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); + const std::vector &getArgs() const { return 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) {} + + std::ostream &dump(std::ostream &out, int ind) { + indent(out, ind) << "FunctionAST\n"; + ++ind; + indent(out, ind) << "Body:"; + return Body ? Body->dump(out, ind) : out << "null\n"; + } + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// 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; + + SourceLocation LitLoc = CurLoc; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(LitLoc, 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(LitLoc, 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() { + SourceLocation IfLoc = CurLoc; + + 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(IfLoc, 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; + SourceLocation BinLoc = CurLoc; + 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(BinLoc, 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; + + SourceLocation FnLoc = CurLoc; + + 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(FnLoc, 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() { + SourceLocation FnLoc = CurLoc; + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = + new PrototypeAST(FnLoc, "main", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Debug Info Support +//===----------------------------------------------------------------------===// + +static DIBuilder *DBuilder; + +DIType DebugInfo::getDoubleTy() { + if (DblTy.isValid()) + return DblTy; + + DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float); + return DblTy; +} + +void DebugInfo::emitLocation(ExprAST *AST) { + if (!AST) + return Builder.SetCurrentDebugLocation(DebugLoc()); + DIScope *Scope; + if (LexicalBlocks.empty()) + Scope = &TheCU; + else + Scope = LexicalBlocks.back(); + Builder.SetCurrentDebugLocation( + DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); +} + +static DICompositeType CreateFunctionType(unsigned NumArgs, DIFile Unit) { + SmallVector EltTys; + DIType DblTy = KSDbgInfo.getDoubleTy(); + + // Add the result type. + EltTys.push_back(DblTy); + + for (unsigned i = 0, e = NumArgs; i != e; ++i) + EltTys.push_back(DblTy); + + DITypeArray EltTypeArray = DBuilder->getOrCreateTypeArray(EltTys); + return DBuilder->createSubroutineType(Unit, EltTypeArray); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static std::map NamedValues; +static legacy::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() { + KSDbgInfo.emitLocation(this); + 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"); + + KSDbgInfo.emitLocation(this); + // 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"); + + KSDbgInfo.emitLocation(this); + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) + return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) + return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) + return 0; + + switch (Op) { + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: + break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // 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() { + KSDbgInfo.emitLocation(this); + + 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); + + KSDbgInfo.emitLocation(this); + + // 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; + } + + KSDbgInfo.emitLocation(this); + + // 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]); + + // Create a subprogram DIE for this function. + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIDescriptor FContext(Unit); + unsigned LineNo = Line; + unsigned ScopeLine = Line; + DISubprogram SP = DBuilder->createFunction( + FContext, Name, StringRef(), Unit, LineNo, + CreateFunctionType(Args.size(), Unit), false /* internal linkage */, + true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + + KSDbgInfo.FnScopeMap[this] = SP; + 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]); + + // Create a debug descriptor for the variable. + DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, + *Scope, Args[Idx], Unit, Line, + KSDbgInfo.getDoubleTy(), Idx); + + Instruction *Call = DBuilder->insertDeclare( + Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); + Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + + // 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; + + // Push the current scope. + KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + + // Unset the location for the prologue emission (leading instructions with no + // location in a function are considered part of the prologue and the debugger + // will run past them when breaking on a function) + KSDbgInfo.emitLocation(nullptr); + + // 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); + + KSDbgInfo.emitLocation(Body); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Pop off the lexical block for the function. + KSDbgInfo.LexicalBlocks.pop_back(); + + // 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()); + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (!F->Codegen()) { + fprintf(stderr, "Error reading function definition:"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (!P->Codegen()) { + fprintf(stderr, "Error reading extern"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (!F->Codegen()) { + fprintf(stderr, "Error generating code for top level expr"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + 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(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + 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. + getNextToken(); + + // Make the module, which holds all the code. + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); + + // Add the current debug info version into the module. + TheModule->addModuleFlag(Module::Warning, "Debug Info Version", + DEBUG_METADATA_VERSION); + + // Darwin only supports dwarf2. + if (Triple(sys::getProcessTriple()).isOSDarwin()) + TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + + // Construct the DIBuilder, we do this here because we need the module. + DBuilder = new DIBuilder(*TheModule); + + // Create the compile unit for the module. + // Currently down as "fib.ks" as a filename since we're redirecting stdin + // but we'd like actual source locations. + KSDbgInfo.TheCU = DBuilder->createCompileUnit( + dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + legacy::FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); + OurFPM.add(new DataLayoutPass()); +#if 0 + // 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()); + #endif + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Finalize the debug info. + DBuilder->finalize(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp index 00f5b83..7f5ed13 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -6,10 +6,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" -#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp index af51b4a..f598ca4 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -9,10 +9,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.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" @@ -36,8 +36,8 @@ 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::opt +UseObjectCache("use-object-cache", cl::desc("Enable use of the MCJIT object caching"), cl::init(false)); @@ -55,14 +55,14 @@ enum Token { // 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 }; @@ -111,11 +111,11 @@ static int gettok() { // 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; @@ -159,7 +159,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -169,7 +169,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -212,7 +212,7 @@ public: VarExprAST(const std::vector > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -227,19 +227,19 @@ 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); }; @@ -250,7 +250,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -274,7 +274,7 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -293,12 +293,12 @@ static ExprAST *ParseExpression(); /// ::= 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; @@ -318,7 +318,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -334,7 +334,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -344,26 +344,26 @@ static ExprAST *ParseParenExpr() { /// 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); } @@ -373,24 +373,24 @@ static ExprAST *ParseForExpr() { 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 == ',') { @@ -398,18 +398,18 @@ static ExprAST *ParseForExpr() { 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)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -419,7 +419,7 @@ static ExprAST *ParseVarExpr() { // 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. @@ -428,29 +428,29 @@ static ExprAST *ParseVarExpr() { 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); } @@ -480,7 +480,7 @@ 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(); @@ -495,20 +495,20 @@ 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(); @@ -516,7 +516,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -528,7 +528,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -538,10 +538,10 @@ static ExprAST *ParseExpression() { /// ::= 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"); @@ -567,7 +567,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -577,23 +577,23 @@ static PrototypeAST *ParsePrototype() { } 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); } @@ -762,14 +762,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// 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. @@ -838,9 +838,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -1027,11 +1027,11 @@ Value *VariableExprAST::Codegen() { 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"); } @@ -1053,11 +1053,11 @@ Value *BinaryExprAST::Codegen() { 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"); @@ -1070,12 +1070,12 @@ Value *BinaryExprAST::Codegen() { "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"); } @@ -1085,7 +1085,7 @@ Value *CallExprAST::Codegen() { 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"); @@ -1095,56 +1095,56 @@ Value *CallExprAST::Codegen() { 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, + 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; @@ -1157,7 +1157,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1170,40 +1170,40 @@ Value *ForExprAST::Codegen() { // 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) { @@ -1213,52 +1213,52 @@ Value *ForExprAST::Codegen() { // 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, + 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: @@ -1271,22 +1271,22 @@ Value *VarExprAST::Codegen() { } 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]; @@ -1297,7 +1297,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), + std::vector Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1314,26 +1314,26 @@ Function *PrototypeAST::Codegen() { // 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; } @@ -1355,19 +1355,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *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); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1428,7 +1428,7 @@ static void HandleTopLevelExpression() { 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; @@ -1465,20 +1465,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +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" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp index 3beb0d8..5294bb7 100644 --- a/examples/Kaleidoscope/MCJIT/complete/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -7,10 +7,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.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" @@ -37,7 +37,7 @@ namespace { cl::value_desc("input IR file name")); cl::opt - VerboseOutput("verbose", + VerboseOutput("verbose", cl::desc("Enable verbose output (results, IR, etc.) to stderr"), cl::init(false)); @@ -830,8 +830,8 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp index 2c1b297..dd35358 100644 --- a/examples/Kaleidoscope/MCJIT/initial/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -6,9 +6,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -32,14 +32,14 @@ enum Token { // 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 }; @@ -88,11 +88,11 @@ static int gettok() { // 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; @@ -136,7 +136,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -146,7 +146,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -189,7 +189,7 @@ public: VarExprAST(const std::vector > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -204,19 +204,19 @@ 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); }; @@ -227,7 +227,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -251,7 +251,7 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -270,12 +270,12 @@ static ExprAST *ParseExpression(); /// ::= 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; @@ -295,7 +295,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -311,7 +311,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -321,26 +321,26 @@ static ExprAST *ParseParenExpr() { /// 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); } @@ -350,24 +350,24 @@ static ExprAST *ParseForExpr() { 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 == ',') { @@ -375,18 +375,18 @@ static ExprAST *ParseForExpr() { 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)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -396,7 +396,7 @@ static ExprAST *ParseVarExpr() { // 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. @@ -405,29 +405,29 @@ static ExprAST *ParseVarExpr() { 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); } @@ -457,7 +457,7 @@ 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(); @@ -472,20 +472,20 @@ 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(); @@ -493,7 +493,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -505,7 +505,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -515,10 +515,10 @@ static ExprAST *ParseExpression() { /// ::= 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"); @@ -544,7 +544,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -554,23 +554,23 @@ static PrototypeAST *ParsePrototype() { } 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); } @@ -670,14 +670,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// 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. @@ -739,9 +739,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -885,11 +885,11 @@ Value *VariableExprAST::Codegen() { 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"); } @@ -911,11 +911,11 @@ Value *BinaryExprAST::Codegen() { 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"); @@ -928,12 +928,12 @@ Value *BinaryExprAST::Codegen() { "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"); } @@ -943,7 +943,7 @@ Value *CallExprAST::Codegen() { 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"); @@ -953,56 +953,56 @@ Value *CallExprAST::Codegen() { 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, + 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; @@ -1015,7 +1015,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1028,40 +1028,40 @@ Value *ForExprAST::Codegen() { // 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) { @@ -1071,52 +1071,52 @@ Value *ForExprAST::Codegen() { // 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, + 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: @@ -1129,22 +1129,22 @@ Value *VarExprAST::Codegen() { } 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]; @@ -1155,7 +1155,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), + std::vector Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1172,26 +1172,26 @@ Function *PrototypeAST::Codegen() { // 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; } @@ -1213,19 +1213,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *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); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1238,7 +1238,7 @@ Function *FunctionAST::Codegen() { return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -1285,7 +1285,7 @@ static void HandleTopLevelExpression() { 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; @@ -1322,20 +1322,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +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" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp index 98c1001..07adbd4 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -6,9 +6,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp index 9c2a0d4..fe7fb61 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -8,9 +8,9 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -34,14 +34,14 @@ enum Token { // 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 }; @@ -90,11 +90,11 @@ static int gettok() { // 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; @@ -138,7 +138,7 @@ class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) + UnaryExprAST(char opcode, ExprAST *operand) : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -148,7 +148,7 @@ class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; @@ -191,7 +191,7 @@ public: VarExprAST(const std::vector > &varnames, ExprAST *body) : VarNames(varnames), Body(body) {} - + virtual Value *Codegen(); }; @@ -206,19 +206,19 @@ 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); }; @@ -229,7 +229,7 @@ class FunctionAST { public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - + Function *Codegen(); }; @@ -253,7 +253,7 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; @@ -272,12 +272,12 @@ static ExprAST *ParseExpression(); /// ::= 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; @@ -297,7 +297,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -313,7 +313,7 @@ static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; - + if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). @@ -323,26 +323,26 @@ static ExprAST *ParseParenExpr() { /// 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); } @@ -352,24 +352,24 @@ static ExprAST *ParseForExpr() { 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 == ',') { @@ -377,18 +377,18 @@ static ExprAST *ParseForExpr() { 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)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { getNextToken(); // eat the var. @@ -398,7 +398,7 @@ static ExprAST *ParseVarExpr() { // 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. @@ -407,29 +407,29 @@ static ExprAST *ParseVarExpr() { 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); } @@ -459,7 +459,7 @@ 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(); @@ -474,20 +474,20 @@ 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(); @@ -495,7 +495,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -507,7 +507,7 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); if (!LHS) return 0; - + return ParseBinOpRHS(0, LHS); } @@ -517,10 +517,10 @@ static ExprAST *ParseExpression() { /// ::= 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"); @@ -546,7 +546,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -556,23 +556,23 @@ static PrototypeAST *ParsePrototype() { } 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); } @@ -673,14 +673,14 @@ private: class HelpingMemoryManager : public SectionMemoryManager { - HelpingMemoryManager(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const HelpingMemoryManager&) LLVM_DELETED_FUNCTION; + HelpingMemoryManager(const HelpingMemoryManager&) = delete; + void operator=(const HelpingMemoryManager&) = delete; public: HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {} virtual ~HelpingMemoryManager() {} - /// This method returns the address of the specified function. + /// 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. @@ -749,9 +749,9 @@ Function *MCJITHelper::getFunction(const std::string FnName) { // If we don't have a prototype yet, create one. if (!PF) - PF = Function::Create(F->getFunctionType(), - Function::ExternalLinkage, - FnName, + PF = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + FnName, OpenModule); return PF; } @@ -925,11 +925,11 @@ Value *VariableExprAST::Codegen() { 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"); } @@ -951,11 +951,11 @@ Value *BinaryExprAST::Codegen() { 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"); @@ -968,12 +968,12 @@ Value *BinaryExprAST::Codegen() { "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"); } @@ -983,7 +983,7 @@ Value *CallExprAST::Codegen() { 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"); @@ -993,56 +993,56 @@ Value *CallExprAST::Codegen() { 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, + 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; @@ -1055,7 +1055,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -1068,40 +1068,40 @@ Value *ForExprAST::Codegen() { // 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) { @@ -1111,52 +1111,52 @@ Value *ForExprAST::Codegen() { // 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, + 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: @@ -1169,22 +1169,22 @@ Value *VarExprAST::Codegen() { } 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]; @@ -1195,7 +1195,7 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), + std::vector Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); @@ -1212,26 +1212,26 @@ Function *PrototypeAST::Codegen() { // 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; } @@ -1253,19 +1253,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *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); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -1326,7 +1326,7 @@ static void HandleTopLevelExpression() { 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; @@ -1363,20 +1363,20 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" +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" +extern "C" double printd(double X) { printf("%f", X); return 0; } -extern "C" +extern "C" double printlf() { printf("\n"); return 0; diff --git a/examples/Kaleidoscope/Makefile b/examples/Kaleidoscope/Makefile index bd0c252..8c3b1e3 100644 --- a/examples/Kaleidoscope/Makefile +++ b/examples/Kaleidoscope/Makefile @@ -10,6 +10,6 @@ LEVEL=../.. include $(LEVEL)/Makefile.config -PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 Chapter8 include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Orc/CMakeLists.txt b/examples/Kaleidoscope/Orc/CMakeLists.txt new file mode 100644 index 0000000..5aa0454 --- /dev/null +++ b/examples/Kaleidoscope/Orc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(initial) +add_subdirectory(lazy_codegen) +add_subdirectory(lazy_irgen) +add_subdirectory(fully_lazy) diff --git a/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt b/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt new file mode 100644 index 0000000..abb0428 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + OrcJIT + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-fully_lazy + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/fully_lazy/Makefile b/examples/Kaleidoscope/Orc/fully_lazy/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/fully_lazy/README.txt b/examples/Kaleidoscope/Orc/fully_lazy/README.txt new file mode 100644 index 0000000..c018931 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/README.txt @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Lazy IRGen Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates fully lazy IR-generation. +Building on the lazy-irgen version of the tutorial, this version injects JIT +callbacks to defer the bulk of IR-generation and code-generation of functions until +they are first called. + +When a function definition is entered, a JIT callback is created and a stub +function is built that will call the body of the function indirectly. The body of +the function is *not* IRGen'd at this point. Instead, the function pointer for +the indirect call is initialized to point at the JIT callback, and the compile +action for the callback is initialized with a lambda that IRGens the body of the +function and adds it to the JIT. The function pointer is updated by the JIT +callback's update action to point at the newly emitted function body, so future +calls to the stub will go straight to the body, not through the JIT. + +This directory contains a Makefile that allows 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. diff --git a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp new file mode 100644 index 0000000..2e65756 --- /dev/null +++ b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp @@ -0,0 +1,1437 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// 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) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr LHS, + std::unique_ptr RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, + std::unique_ptr Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr Start, + std::unique_ptr End, std::unique_ptr Step, + std::unique_ptr Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair> Binding; + typedef std::vector BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + 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]; + } + + std::string Name; + std::vector Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr Proto, + std::unique_ptr Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr Proto; + std::unique_ptr 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; +} + +template +std::unique_ptr ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique(IdName); + + // Call. + getNextToken(); // eat ( + std::vector> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr ParseNumberExpr() { + auto Result = llvm::make_unique(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr ParsePrimary() { + switch (CurTok) { + default: return ErrorU("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 std::unique_ptr 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 (auto Operand = ParseUnary()) + return llvm::make_unique(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr ParseBinOpRHS(int ExprPrec, + std::unique_ptr 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. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // 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, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("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 ErrorU("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU("Invalid number of operands for operator"); + + return llvm::make_unique(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique("__anon_expr", std::vector()); + return llvm::make_unique(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // 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) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map NamedValues; +private: + SessionContext &Session; + std::unique_ptr M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// 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::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().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. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // 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 = C.getBuilder().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->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().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. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().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 = C.NamedValues[VarName]; + C.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->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + 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 = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().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. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[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->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // 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, FnName, + &C.getM()); + + // 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 = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP("redefinition of function with different # args"); + return nullptr; + } + } + + // 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, IRGenContext &C) { + 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. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().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 nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +static void EarthShatteringKaboom() { + fprintf(stderr, "Earth shattering kaboom."); + exit(1); +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef LazyEmittingLayer LazyEmitLayerT; + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Session(Session), + Mang(Session.getTarget().getDataLayout()), + ObjectLayer( + [](){ return llvm::make_unique(); }), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer), + CompileCallbacks(LazyEmitLayer, Session.getLLVMContext(), + reinterpret_cast(EarthShatteringKaboom), + 64) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + void addFunctionDefinition(std::unique_ptr FnAST) { + FunctionDefs[mangle(FnAST->Proto->Name)] = std::move(FnAST); + } + + ModuleHandleT addModule(std::unique_ptr M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return Symbol.getAddress(); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchUncompiledASTs(Name); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { + return LazyEmitLayer.findSymbolIn(H, Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string &Name) { + return findSymbol(mangle(Name)); + } + + JITSymbol findUnmangledSymbolIn(ModuleHandleT H, const std::string &Name) { + return findSymbolIn(H, mangle(Name)); + } + +private: + + // This method searches the FunctionDefs map for a definition of 'Name'. If it + // finds one it generates a stub for it and returns the address of the stub. + TargetAddress searchUncompiledASTs(const std::string &Name) { + auto DefI = FunctionDefs.find(Name); + if (DefI == FunctionDefs.end()) + return 0; + + // We have AST for 'Name'. IRGen a stub for it and add it to the JIT. + // FIXME: What happens if IRGen fails? + auto H = irGenStub(std::move(DefI->second)); + + // Remove the function definition's AST now that we're + // finished with it. + FunctionDefs.erase(DefI); + + // Return the address of the stub. + return findSymbolIn(H, Name).getAddress(); + } + + // This method will take the AST for a function definition and IR-gen a stub + // for that function that will, on first call, IR-gen the actual body of the + // function. + ModuleHandleT irGenStub(std::unique_ptr FnAST) { + // Step 1) IRGen a prototype for the stub. This will have the same type as + // the function. + IRGenContext C(Session); + Function *F = FnAST->Proto->IRGen(C); + + // Step 2) Get a compile callback that can be used to compile the body of + // the function. The resulting CallbackInfo type will let us set the + // compile and update actions for the callback, and get a pointer to + // the jit trampoline that we need to call to trigger those actions. + auto CallbackInfo = + CompileCallbacks.getCompileCallback(*F->getFunctionType()); + + // Step 3) Create a stub that will indirectly call the body of this + // function once it is compiled. Initially, set the function + // pointer for the indirection to point at the trampoline. + std::string BodyPtrName = (F->getName() + "$address").str(); + GlobalVariable *FunctionBodyPointer = + createImplPointer(*F, BodyPtrName, CallbackInfo.getAddress()); + makeStub(*F, *FunctionBodyPointer); + + // Step 4) Add the module containing the stub to the JIT. + auto H = addModule(C.takeM()); + + // Step 5) Set the compile and update actions. + // + // The compile action will IRGen the function and add it to the JIT, then + // request its address, which will trigger codegen. Since we don't need the + // AST after this, we pass ownership of the AST into the compile action: + // compile actions (and update actions) are deleted after they're run, so + // this will free the AST for us. + // + // The update action will update FunctionBodyPointer to point at the newly + // compiled function. + std::shared_ptr Fn = std::move(FnAST); + CallbackInfo.setCompileAction([this, Fn]() { + auto H = addModule(IRGen(Session, *Fn)); + return findUnmangledSymbolIn(H, Fn->Proto->Name).getAddress(); + }); + CallbackInfo.setUpdateAction( + CompileCallbacks.getLocalFPUpdater(H, mangle(BodyPtrName))); + + return H; + } + + SessionContext &Session; + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; + + std::map> FunctionDefs; + + JITCompileCallbackManager CompileCallbacks; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + S.addPrototypeAST(llvm::make_unique(*F->Proto)); + J.addFunctionDefinition(std::move(F)); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // 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)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "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(); + + // 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 + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/initial/CMakeLists.txt b/examples/Kaleidoscope/Orc/initial/CMakeLists.txt new file mode 100644 index 0000000..4f21e1c --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-initial + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/initial/Makefile b/examples/Kaleidoscope/Orc/initial/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/initial/README.txt b/examples/Kaleidoscope/Orc/initial/README.txt new file mode 100644 index 0000000..5f4cbbf --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/README.txt @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Initial Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates fully eager compilation. When +a function definition or top-level expression is entered it is immediately +translated (IRGen'd) to LLVM IR and added to the JIT, where it is code-gen'd to +native code and either stored (for function definitions) or executed (for +top-level expressions). + +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. diff --git a/examples/Kaleidoscope/Orc/initial/toy.cpp b/examples/Kaleidoscope/Orc/initial/toy.cpp new file mode 100644 index 0000000..1b65e8c --- /dev/null +++ b/examples/Kaleidoscope/Orc/initial/toy.cpp @@ -0,0 +1,1333 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// 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) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr LHS, + std::unique_ptr RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, + std::unique_ptr Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr Start, + std::unique_ptr End, std::unique_ptr Step, + std::unique_ptr Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair> Binding; + typedef std::vector BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + 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]; + } + + std::string Name; + std::vector Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr Proto, + std::unique_ptr Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr Proto; + std::unique_ptr 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; +} + +template +std::unique_ptr ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique(IdName); + + // Call. + getNextToken(); // eat ( + std::vector> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr ParseNumberExpr() { + auto Result = llvm::make_unique(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr ParsePrimary() { + switch (CurTok) { + default: return ErrorU("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 std::unique_ptr 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 (auto Operand = ParseUnary()) + return llvm::make_unique(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr ParseBinOpRHS(int ExprPrec, + std::unique_ptr 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. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // 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, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("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 ErrorU("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU("Invalid number of operands for operator"); + + return llvm::make_unique(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique("__anon_expr", std::vector()); + return llvm::make_unique(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // 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) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map NamedValues; +private: + SessionContext &Session; + std::unique_ptr M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// 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::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().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. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // 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 = C.getBuilder().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->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().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. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().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 = C.NamedValues[VarName]; + C.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->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + 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 = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().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. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[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->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // 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, FnName, + &C.getM()); + + // 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 = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP("redefinition of function with different # args"); + return nullptr; + } + } + + // 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, IRGenContext &C) { + 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. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().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 nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + ModuleHandleT addModule(std::unique_ptr M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM( + [&](const std::string &Name) { + return findSymbol(Name).getAddress(); + }, + [](const std::string &S) { return 0; } ); + + return CompileLayer.addModuleSet(singletonSet(std::move(M)), std::move(MM)); + } + + void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return CompileLayer.findSymbol(Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); + } + +private: + + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + if (auto M = IRGen(S, *F)) { + S.addPrototypeAST(llvm::make_unique(*F->Proto)); + J.addModule(std::move(M)); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // 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)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "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(); + + // 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 + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt b/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt new file mode 100644 index 0000000..faad342 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-lazy_codegen + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/Makefile b/examples/Kaleidoscope/Orc/lazy_codegen/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/README.txt b/examples/Kaleidoscope/Orc/lazy_codegen/README.txt new file mode 100644 index 0000000..9d62a91 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/README.txt @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Initial Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates lazy code-generation. +Unlike the first Kaleidoscope-Orc tutorial, where code-gen was performed as soon +as modules were added to the JIT, this tutorial adds a LazyEmittingLayer to defer +code-generation until modules are actually referenced. All IR-generation is still +performed up-front. + +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. diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp new file mode 100644 index 0000000..1ed267d --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp @@ -0,0 +1,1338 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// 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) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr LHS, + std::unique_ptr RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, + std::unique_ptr Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr Start, + std::unique_ptr End, std::unique_ptr Step, + std::unique_ptr Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair> Binding; + typedef std::vector BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + 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]; + } + + std::string Name; + std::vector Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr Proto, + std::unique_ptr Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr Proto; + std::unique_ptr 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; +} + +template +std::unique_ptr ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique(IdName); + + // Call. + getNextToken(); // eat ( + std::vector> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr ParseNumberExpr() { + auto Result = llvm::make_unique(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr ParsePrimary() { + switch (CurTok) { + default: return ErrorU("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 std::unique_ptr 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 (auto Operand = ParseUnary()) + return llvm::make_unique(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr ParseBinOpRHS(int ExprPrec, + std::unique_ptr 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. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // 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, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("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 ErrorU("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU("Invalid number of operands for operator"); + + return llvm::make_unique(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique("__anon_expr", std::vector()); + return llvm::make_unique(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // 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) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map NamedValues; +private: + SessionContext &Session; + std::unique_ptr M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// 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::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().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. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // 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 = C.getBuilder().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->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().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. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().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 = C.NamedValues[VarName]; + C.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->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + 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 = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().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. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[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->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // 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, FnName, + &C.getM()); + + // 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 = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP("redefinition of function with different # args"); + return nullptr; + } + } + + // 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, IRGenContext &C) { + 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. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().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 nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef LazyEmittingLayer LazyEmitLayerT; + + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + ModuleHandleT addModule(std::unique_ptr M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM( + [&](const std::string &Name) { + return findSymbol(Name).getAddress(); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string Name) { + return findSymbol(mangle(Name)); + } + +private: + + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + if (auto M = IRGen(S, *F)) { + S.addPrototypeAST(llvm::make_unique(*F->Proto)); + J.addModule(std::move(M)); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // 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)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "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(); + + // 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 + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt b/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt new file mode 100644 index 0000000..4488681 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + Object + RuntimeDyld + Support + native + ) + +add_kaleidoscope_chapter(Kaleidoscope-Orc-lazy_irgen + toy.cpp + ) diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/Makefile b/examples/Kaleidoscope/Orc/lazy_irgen/Makefile new file mode 100644 index 0000000..5536314 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/Makefile @@ -0,0 +1,17 @@ +UNAME := $(shell uname -s) + +ifeq ($(UNAME),Darwin) + CXX := xcrun --sdk macosx clang++ +else + CXX := clang++ +endif + +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core orcjit native) + +toy: toy.cpp + $(CXX) $(LLVM_CXXFLAGS) -Wall -std=c++11 -g -O0 -rdynamic -fno-rtti -o toy toy.cpp $(LLVM_LDFLAGS) + +.PHONY: clean +clean: + rm -f toy diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/README.txt b/examples/Kaleidoscope/Orc/lazy_irgen/README.txt new file mode 100644 index 0000000..9aaa431 --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/README.txt @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===/ +// Kaleidoscope with Orc - Lazy IRGen Version +//===----------------------------------------------------------------------===// + +This version of Kaleidoscope with Orc demonstrates lazy IR-generation. +Building on the lazy-codegen version of the tutorial, this version reduces the +amount of up-front work that must be done by lazily IRgen'ing ASTs. When a +function definition is entered, its AST is added to a map of available +definitions. No IRGen is performed at this point and nothing is added to the JIT. +When attempting to resolve symbol addresses, the lambda in +KaleidoscopeJIT::getSymbolAddress will scan the AST map and generate IR on the +fly. + +This directory contains a Makefile that allows 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. diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp new file mode 100644 index 0000000..d7744ec --- /dev/null +++ b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp @@ -0,0 +1,1373 @@ +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvm::orc; + +//===----------------------------------------------------------------------===// +// 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) +//===----------------------------------------------------------------------===// + +class IRGenContext; + +/// ExprAST - Base class for all expression nodes. +struct ExprAST { + virtual ~ExprAST() {} + virtual Value *IRGen(IRGenContext &C) const = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +struct NumberExprAST : public ExprAST { + NumberExprAST(double Val) : Val(Val) {} + Value *IRGen(IRGenContext &C) const override; + + double Val; +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +struct VariableExprAST : public ExprAST { + VariableExprAST(std::string Name) : Name(std::move(Name)) {} + Value *IRGen(IRGenContext &C) const override; + + std::string Name; +}; + +/// UnaryExprAST - Expression class for a unary operator. +struct UnaryExprAST : public ExprAST { + UnaryExprAST(char Opcode, std::unique_ptr Operand) + : Opcode(std::move(Opcode)), Operand(std::move(Operand)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Opcode; + std::unique_ptr Operand; +}; + +/// BinaryExprAST - Expression class for a binary operator. +struct BinaryExprAST : public ExprAST { + BinaryExprAST(char Op, std::unique_ptr LHS, + std::unique_ptr RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + + Value *IRGen(IRGenContext &C) const override; + + char Op; + std::unique_ptr LHS, RHS; +}; + +/// CallExprAST - Expression class for function calls. +struct CallExprAST : public ExprAST { + CallExprAST(std::string CalleeName, + std::vector> Args) + : CalleeName(std::move(CalleeName)), Args(std::move(Args)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string CalleeName; + std::vector> Args; +}; + +/// IfExprAST - Expression class for if/then/else. +struct IfExprAST : public ExprAST { + IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, + std::unique_ptr Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *IRGen(IRGenContext &C) const override; + + std::unique_ptr Cond, Then, Else; +}; + +/// ForExprAST - Expression class for for/in. +struct ForExprAST : public ExprAST { + ForExprAST(std::string VarName, std::unique_ptr Start, + std::unique_ptr End, std::unique_ptr Step, + std::unique_ptr Body) + : VarName(std::move(VarName)), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + std::string VarName; + std::unique_ptr Start, End, Step, Body; +}; + +/// VarExprAST - Expression class for var/in +struct VarExprAST : public ExprAST { + typedef std::pair> Binding; + typedef std::vector BindingList; + + VarExprAST(BindingList VarBindings, std::unique_ptr Body) + : VarBindings(std::move(VarBindings)), Body(std::move(Body)) {} + + Value *IRGen(IRGenContext &C) const override; + + BindingList VarBindings; + std::unique_ptr Body; +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +struct PrototypeAST { + PrototypeAST(std::string Name, std::vector Args, + bool IsOperator = false, unsigned Precedence = 0) + : Name(std::move(Name)), Args(std::move(Args)), IsOperator(IsOperator), + Precedence(Precedence) {} + + Function *IRGen(IRGenContext &C) const; + void CreateArgumentAllocas(Function *F, IRGenContext &C); + + 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]; + } + + std::string Name; + std::vector Args; + bool IsOperator; + unsigned Precedence; // Precedence if a binary op. +}; + +/// FunctionAST - This class represents a function definition itself. +struct FunctionAST { + FunctionAST(std::unique_ptr Proto, + std::unique_ptr Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + + Function *IRGen(IRGenContext &C) const; + + std::unique_ptr Proto; + std::unique_ptr 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; +} + +template +std::unique_ptr ErrorU(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +template +T* ErrorP(const std::string &Str) { + std::cerr << "Error: " << Str << "\n"; + return nullptr; +} + +static std::unique_ptr ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static std::unique_ptr ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return llvm::make_unique(IdName); + + // Call. + getNextToken(); // eat ( + std::vector> Args; + if (CurTok != ')') { + while (1) { + auto Arg = ParseExpression(); + if (!Arg) return nullptr; + Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + + if (CurTok != ',') + return ErrorU("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return llvm::make_unique(IdName, std::move(Args)); +} + +/// numberexpr ::= number +static std::unique_ptr ParseNumberExpr() { + auto Result = llvm::make_unique(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static std::unique_ptr ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return ErrorU("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static std::unique_ptr ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + auto Cond = ParseExpression(); + if (!Cond) + return nullptr; + + if (CurTok != tok_then) + return ErrorU("expected then"); + getNextToken(); // eat the then + + auto Then = ParseExpression(); + if (!Then) + return nullptr; + + if (CurTok != tok_else) + return ErrorU("expected else"); + + getNextToken(); + + auto Else = ParseExpression(); + if (!Else) + return nullptr; + + return llvm::make_unique(std::move(Cond), std::move(Then), + std::move(Else)); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static std::unique_ptr ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return ErrorU("expected '=' after for"); + getNextToken(); // eat '='. + + + auto Start = ParseExpression(); + if (!Start) + return nullptr; + if (CurTok != ',') + return ErrorU("expected ',' after for start value"); + getNextToken(); + + auto End = ParseExpression(); + if (!End) + return nullptr; + + // The step value is optional. + std::unique_ptr Step; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (!Step) + return nullptr; + } + + if (CurTok != tok_in) + return ErrorU("expected 'in' after for"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (Body) + return nullptr; + + return llvm::make_unique(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static std::unique_ptr ParseVarExpr() { + getNextToken(); // eat the var. + + VarExprAST::BindingList VarBindings; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return ErrorU("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + std::unique_ptr Init; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (!Init) + return nullptr; + } + + VarBindings.push_back(VarExprAST::Binding(Name, std::move(Init))); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return ErrorU("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return ErrorU("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + auto Body = ParseExpression(); + if (!Body) + return nullptr; + + return llvm::make_unique(std::move(VarBindings), std::move(Body)); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static std::unique_ptr ParsePrimary() { + switch (CurTok) { + default: return ErrorU("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 std::unique_ptr 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 (auto Operand = ParseUnary()) + return llvm::make_unique(Opc, std::move(Operand)); + return nullptr; +} + +/// binoprhs +/// ::= ('+' unary)* +static std::unique_ptr ParseBinOpRHS(int ExprPrec, + std::unique_ptr 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. + auto RHS = ParseUnary(); + if (!RHS) + return nullptr; + + // 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, std::move(RHS)); + if (!RHS) + return nullptr; + } + + // Merge LHS/RHS. + LHS = llvm::make_unique(BinOp, std::move(LHS), std::move(RHS)); + } +} + +/// expression +/// ::= unary binoprhs +/// +static std::unique_ptr ParseExpression() { + auto LHS = ParseUnary(); + if (!LHS) + return nullptr; + + return ParseBinOpRHS(0, std::move(LHS)); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static std::unique_ptr ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorU("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorU("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 ErrorU("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorU("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorU("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorU("Invalid number of operands for operator"); + + return llvm::make_unique(FnName, std::move(ArgNames), Kind != 0, + BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static std::unique_ptr ParseDefinition() { + getNextToken(); // eat def. + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; + + if (auto Body = ParseExpression()) + return llvm::make_unique(std::move(Proto), std::move(Body)); + return nullptr; +} + +/// toplevelexpr ::= expression +static std::unique_ptr ParseTopLevelExpr() { + if (auto E = ParseExpression()) { + // Make an anonymous proto. + auto Proto = + llvm::make_unique("__anon_expr", std::vector()); + return llvm::make_unique(std::move(Proto), std::move(E)); + } + return nullptr; +} + +/// external ::= 'extern' prototype +static std::unique_ptr ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +// FIXME: Obviously we can do better than this +std::string GenerateUniqueName(const std::string &Root) { + static int i = 0; + std::ostringstream NameStream; + NameStream << Root << ++i; + return NameStream.str(); +} + +std::string MakeLegalFunctionName(std::string Name) +{ + std::string NewName; + assert(!Name.empty() && "Base name must not be empty"); + + // 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) { + std::ostringstream NumStream; + NumStream << (int)NewName.at(pos); + NewName = NewName.replace(pos, 1, NumStream.str()); + } + + return NewName; +} + +class SessionContext { +public: + SessionContext(LLVMContext &C) + : Context(C), TM(EngineBuilder().selectTarget()) {} + LLVMContext& getLLVMContext() const { return Context; } + TargetMachine& getTarget() { return *TM; } + void addPrototypeAST(std::unique_ptr P); + PrototypeAST* getPrototypeAST(const std::string &Name); +private: + typedef std::map> PrototypeMap; + + LLVMContext &Context; + std::unique_ptr TM; + + PrototypeMap Prototypes; +}; + +void SessionContext::addPrototypeAST(std::unique_ptr P) { + Prototypes[P->Name] = std::move(P); +} + +PrototypeAST* SessionContext::getPrototypeAST(const std::string &Name) { + PrototypeMap::iterator I = Prototypes.find(Name); + if (I != Prototypes.end()) + return I->second.get(); + return nullptr; +} + +class IRGenContext { +public: + + IRGenContext(SessionContext &S) + : Session(S), + M(new Module(GenerateUniqueName("jit_module_"), + Session.getLLVMContext())), + Builder(Session.getLLVMContext()) { + M->setDataLayout(Session.getTarget().getDataLayout()); + } + + SessionContext& getSession() { return Session; } + Module& getM() const { return *M; } + std::unique_ptr takeM() { return std::move(M); } + IRBuilder<>& getBuilder() { return Builder; } + LLVMContext& getLLVMContext() { return Session.getLLVMContext(); } + Function* getPrototype(const std::string &Name); + + std::map NamedValues; +private: + SessionContext &Session; + std::unique_ptr M; + IRBuilder<> Builder; +}; + +Function* IRGenContext::getPrototype(const std::string &Name) { + if (Function *ExistingProto = M->getFunction(Name)) + return ExistingProto; + if (PrototypeAST *ProtoAST = Session.getPrototypeAST(Name)) + return ProtoAST->IRGen(*this); + return nullptr; +} + +/// 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::IRGen(IRGenContext &C) const { + return ConstantFP::get(C.getLLVMContext(), APFloat(Val)); +} + +Value *VariableExprAST::IRGen(IRGenContext &C) const { + // Look this variable up in the function. + Value *V = C.NamedValues[Name]; + + if (V == 0) + return ErrorP("Unknown variable name '" + Name + "'"); + + // Load the value. + return C.getBuilder().CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::IRGen(IRGenContext &C) const { + if (Value *OperandV = Operand->IRGen(C)) { + std::string FnName = MakeLegalFunctionName(std::string("unary")+Opcode); + if (Function *F = C.getPrototype(FnName)) + return C.getBuilder().CreateCall(F, OperandV, "unop"); + return ErrorP("Unknown unary operator"); + } + + // Could not codegen operand - return null. + return nullptr; +} + +Value *BinaryExprAST::IRGen(IRGenContext &C) const { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + auto LHSVar = static_cast(*LHS); + // Codegen the RHS. + Value *Val = RHS->IRGen(C); + if (!Val) return nullptr; + + // Look up the name. + if (auto Variable = C.NamedValues[LHSVar.Name]) { + C.getBuilder().CreateStore(Val, Variable); + return Val; + } + return ErrorP("Unknown variable name"); + } + + Value *L = LHS->IRGen(C); + Value *R = RHS->IRGen(C); + if (!L || !R) return nullptr; + + switch (Op) { + case '+': return C.getBuilder().CreateFAdd(L, R, "addtmp"); + case '-': return C.getBuilder().CreateFSub(L, R, "subtmp"); + case '*': return C.getBuilder().CreateFMul(L, R, "multmp"); + case '/': return C.getBuilder().CreateFDiv(L, R, "divtmp"); + case '<': + L = C.getBuilder().CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return C.getBuilder().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. + std::string FnName = MakeLegalFunctionName(std::string("binary")+Op); + if (Function *F = C.getPrototype(FnName)) { + Value *Ops[] = { L, R }; + return C.getBuilder().CreateCall(F, Ops, "binop"); + } + + return ErrorP("Unknown binary operator"); +} + +Value *CallExprAST::IRGen(IRGenContext &C) const { + // Look up the name in the global module table. + if (auto CalleeF = C.getPrototype(CalleeName)) { + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorP("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->IRGen(C)); + if (!ArgsV.back()) return nullptr; + } + + return C.getBuilder().CreateCall(CalleeF, ArgsV, "calltmp"); + } + + return ErrorP("Unknown function referenced"); +} + +Value *IfExprAST::IRGen(IRGenContext &C) const { + Value *CondV = Cond->IRGen(C); + if (!CondV) return nullptr; + + // Convert condition to a bool by comparing equal to 0.0. + ConstantFP *FPZero = + ConstantFP::get(C.getLLVMContext(), APFloat(0.0)); + CondV = C.getBuilder().CreateFCmpONE(CondV, FPZero, "ifcond"); + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(C.getLLVMContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(C.getLLVMContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(C.getLLVMContext(), "ifcont"); + + C.getBuilder().CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + C.getBuilder().SetInsertPoint(ThenBB); + + Value *ThenV = Then->IRGen(C); + if (!ThenV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = C.getBuilder().GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + C.getBuilder().SetInsertPoint(ElseBB); + + Value *ElseV = Else->IRGen(C); + if (!ElseV) return nullptr; + + C.getBuilder().CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = C.getBuilder().GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + C.getBuilder().SetInsertPoint(MergeBB); + PHINode *PN = C.getBuilder().CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::IRGen(IRGenContext &C) const { + // 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 = C.getBuilder().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->IRGen(C); + if (!StartVal) return nullptr; + + // Store the value into the alloca. + C.getBuilder().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. + C.getBuilder().CreateBr(LoopBB); + + // Start insertion in LoopBB. + C.getBuilder().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 = C.NamedValues[VarName]; + C.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->IRGen(C)) + return nullptr; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->IRGen(C); + if (!StepVal) return nullptr; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->IRGen(C); + 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 = C.getBuilder().CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = C.getBuilder().CreateFAdd(CurVar, StepVal, "nextvar"); + C.getBuilder().CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = C.getBuilder().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. + C.getBuilder().CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + C.getBuilder().SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + C.NamedValues[VarName] = OldVal; + else + C.NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::IRGen(IRGenContext &C) const { + std::vector OldBindings; + + Function *TheFunction = C.getBuilder().GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) { + auto &VarName = VarBindings[i].first; + auto &Init = VarBindings[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->IRGen(C); + if (!InitVal) return nullptr; + } else // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + C.getBuilder().CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(C.NamedValues[VarName]); + + // Remember this binding. + C.NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->IRGen(C); + if (!BodyVal) return nullptr; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarBindings.size(); i != e; ++i) + C.NamedValues[VarBindings[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::IRGen(IRGenContext &C) const { + std::string FnName = MakeLegalFunctionName(Name); + + // 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, FnName, + &C.getM()); + + // 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 = C.getM().getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorP("redefinition of function"); + return nullptr; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorP("redefinition of function with different # args"); + return nullptr; + } + } + + // 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, IRGenContext &C) { + 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. + C.getBuilder().CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + C.NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::IRGen(IRGenContext &C) const { + C.NamedValues.clear(); + + Function *TheFunction = Proto->IRGen(C); + if (!TheFunction) + return nullptr; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->Precedence; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + C.getBuilder().SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction, C); + + if (Value *RetVal = Body->IRGen(C)) { + // Finish off the function. + C.getBuilder().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 nullptr; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static std::unique_ptr IRGen(SessionContext &S, + const FunctionAST &F) { + IRGenContext C(S); + auto LF = F.IRGen(C); + if (!LF) + return nullptr; +#ifndef MINIMAL_STDERR_OUTPUT + fprintf(stderr, "Read function definition:"); + LF->dump(); +#endif + return C.takeM(); +} + +template +static std::vector singletonSet(T t) { + std::vector Vec; + Vec.push_back(std::move(t)); + return Vec; +} + +class KaleidoscopeJIT { +public: + typedef ObjectLinkingLayer<> ObjLayerT; + typedef IRCompileLayer CompileLayerT; + typedef LazyEmittingLayer LazyEmitLayerT; + typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; + + KaleidoscopeJIT(SessionContext &Session) + : Session(Session), + Mang(Session.getTarget().getDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} + + std::string mangle(const std::string &Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + void addFunctionDefinition(std::unique_ptr FnAST) { + FunctionDefs[mangle(FnAST->Proto->Name)] = std::move(FnAST); + } + + ModuleHandleT addModule(std::unique_ptr M) { + // We need a memory manager to allocate memory and resolve symbols for this + // new module. Create one that resolves symbols by looking back into the + // JIT. + auto MM = createLookasideRTDyldMM( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return Symbol.getAddress(); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchUncompiledASTs(Name); + }, + [](const std::string &S) { return 0; } ); + + return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), + std::move(MM)); + } + + void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } + + JITSymbol findSymbol(const std::string &Name) { + return LazyEmitLayer.findSymbol(Name, true); + } + + JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { + return LazyEmitLayer.findSymbolIn(H, Name, true); + } + + JITSymbol findUnmangledSymbol(const std::string &Name) { + return findSymbol(mangle(Name)); + } + +private: + + // This method searches the FunctionDefs map for a definition of 'Name'. If it + // finds one it generates a stub for it and returns the address of the stub. + TargetAddress searchUncompiledASTs(const std::string &Name) { + auto DefI = FunctionDefs.find(Name); + if (DefI == FunctionDefs.end()) + return 0; + + // We have AST for 'Name'. IRGen it, add it to the JIT, and + // return the address for it. + // FIXME: What happens if IRGen fails? + auto H = addModule(IRGen(Session, *DefI->second)); + + // Remove the function definition's AST now that we're + // finished with it. + FunctionDefs.erase(DefI); + + // Return the address of the function. + return findSymbolIn(H, Name).getAddress(); + } + + SessionContext &Session; + Mangler Mang; + ObjLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; + + std::map> FunctionDefs; +}; + +static void HandleDefinition(SessionContext &S, KaleidoscopeJIT &J) { + if (auto F = ParseDefinition()) { + S.addPrototypeAST(llvm::make_unique(*F->Proto)); + J.addFunctionDefinition(std::move(F)); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern(SessionContext &S) { + if (auto P = ParseExtern()) + S.addPrototypeAST(std::move(P)); + else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) { + // Evaluate a top-level expression into an anonymous function. + if (auto F = ParseTopLevelExpr()) { + IRGenContext C(S); + if (auto ExprFunc = F->IRGen(C)) { +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "Expression function:\n"; + ExprFunc->dump(); +#endif + // Add the CodeGen'd module to the JIT. Keep a handle to it: We can remove + // this module as soon as we've executed Function ExprFunc. + auto H = J.addModule(C.takeM()); + + // Get the address of the JIT'd function in memory. + auto ExprSymbol = J.findUnmangledSymbol("__anon_expr"); + + // 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)ExprSymbol.getAddress(); +#ifdef MINIMAL_STDERR_OUTPUT + FP(); +#else + std::cerr << "Evaluated to " << FP() << "\n"; +#endif + + // Remove the function. + J.removeModule(H); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + SessionContext S(getGlobalContext()); + KaleidoscopeJIT J(S); + + while (1) { + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); continue; // ignore top-level semicolons. + case tok_def: HandleDefinition(S, J); break; + case tok_extern: HandleExtern(S); break; + default: HandleTopLevelExpression(S, J); break; + } +#ifndef MINIMAL_STDERR_OUTPUT + std::cerr << "ready> "; +#endif + } +} + +//===----------------------------------------------------------------------===// +// "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(); + + // 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 + std::cerr << "ready> "; +#endif + getNextToken(); + + std::cerr << std::fixed; + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} + diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 30c7595..8873fdb 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -1157,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Argument) \ macro(BasicBlock) \ macro(InlineAsm) \ - macro(MDNode) \ - macro(MDString) \ macro(User) \ macro(Constant) \ macro(BlockAddress) \ @@ -1307,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); LLVMValueRef LLVMIsA##name(LLVMValueRef Val); LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); + /** * @} */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index f1f4cad..eb3ecab 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -170,6 +170,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h index 9f337cf..cedde5e 100644 --- a/include/llvm-c/Linker.h +++ b/include/llvm-c/Linker.h @@ -20,20 +20,13 @@ extern "C" { #endif - -typedef enum { - LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */ - LLVMLinkerPreserveSource = 1 /* Preserve the source module. */ -} LLVMLinkerMode; - - /* Links the source module into the destination module, taking ownership * of the source module away from the caller. Optionally returns a * human-readable description of any errors that occurred in linking. * OutMessage must be disposed with LLVMDisposeMessage. The return value * is true if an error occurred, false otherwise. */ LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - LLVMLinkerMode Mode, char **OutMessage); + unsigned Unused, char **OutMessage); #ifdef __cplusplus } diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 7ad1ad1..48c19a6 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -35,6 +35,9 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); +/** See llvm::createBitTrackingDCEPass function. */ +void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM); + /** See llvm::createAlignmentFromAssumptionsPass function. */ void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 3f30d6d..c6acdad 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 11 +#define LTO_API_VERSION 13 /** * \since prior to LTO_API_VERSION=3 @@ -396,6 +396,17 @@ extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); /** + * Sets the object module for code generation. This will transfer the ownship of + * the module to code generator. + * + * \c cg and \c mod must both be in the same context. + * + * \since prior to LTO_API_VERSION=13 + */ +extern void +lto_codegen_set_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). * @@ -464,6 +475,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized. + * * On success returns a pointer to a generated mach-o/ELF buffer and * length set to the buffer size. The buffer is owned by the * lto_code_gen_t and will be freed when lto_codegen_dispose() @@ -477,6 +490,9 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized (instead + * of returning a generated mach-o/ELF buffer, it writes to a file). + * * The name of the file is written to name. Returns true on error. * * \since LTO_API_VERSION=5 @@ -484,6 +500,36 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); +/** + * Runs optimization for the merged module. Returns true on error. + * + * \since LTO_API_VERSION=12 + */ +extern lto_bool_t +lto_codegen_optimize(lto_code_gen_t cg); + +/** + * Generates code for the optimized merged module into one native object file. + * It will not run any IR optimizations on the merged module. + * + * On success returns a pointer to a generated mach-o/ELF buffer and length set + * to the buffer size. The buffer is owned by the lto_code_gen_t and will be + * freed when lto_codegen_dispose() is called, or + * lto_codegen_compile_optimized() is called again. On failure, returns NULL + * (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=12 + */ +extern const void* +lto_codegen_compile_optimized(lto_code_gen_t cg, size_t* length); + +/** + * Returns the runtime API version. + * + * \since LTO_API_VERSION=12 + */ +extern unsigned int +lto_api_version(void); /** * Sets options to help debug codegen bugs. diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 26aae77..bf814e0 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -376,7 +376,7 @@ public: /// 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; + bool operator==(const APFloat &) const = delete; /// IEEE comparison with another floating point number (NaNs compare /// unordered, 0==-0). diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index f4e7e3c..c2fe094 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -91,6 +91,8 @@ class APInt { APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) }; + friend struct DenseMapAPIntKeyInfo; + /// \brief Fast internal constructor /// /// This constructor is used only internally for speed of construction of @@ -277,7 +279,6 @@ public: /// Simply makes *this a copy of that. /// @brief Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; else @@ -1355,7 +1356,7 @@ public: /// \brief Count the number of leading one bits. /// - /// This function is an APInt version of the countLeadingOnes_{32,64} + /// This function is an APInt version of the countLeadingOnes /// functions in MathExtras.h. It counts the number of ones from the most /// significant bit to the first zero bit. /// @@ -1371,7 +1372,7 @@ public: /// \brief Count the number of trailing zero bits. /// - /// This function is an APInt version of the countTrailingZeros_{32,64} + /// This function is an APInt version of the countTrailingZeros /// functions in MathExtras.h. It counts the number of zeros from the least /// significant bit to the first set bit. /// @@ -1381,7 +1382,7 @@ public: /// \brief Count the number of trailing one bits. /// - /// This function is an APInt version of the countTrailingOnes_{32,64} + /// This function is an APInt version of the countTrailingOnes /// functions in MathExtras.h. It counts the number of ones from the least /// significant bit to the first zero bit. /// @@ -1389,19 +1390,19 @@ public: /// of ones from the least significant bit to the first zero bit. unsigned countTrailingOnes() const { if (isSingleWord()) - return CountTrailingOnes_64(VAL); + return llvm::countTrailingOnes(VAL); return countTrailingOnesSlowCase(); } /// \brief Count the number of bits set. /// - /// This function is an APInt version of the countPopulation_{32,64} functions + /// This function is an APInt version of the countPopulation 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); + return llvm::countPopulation(VAL); return countPopulationSlowCase(); } diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index a6693f7..91ccda2 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -62,6 +62,12 @@ public: } using APInt::toString; + /// \brief Get the correctly-extended \c int64_t value. + int64_t getExtValue() const { + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return isSigned() ? getSExtValue() : getZExtValue(); + } + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } @@ -133,14 +139,27 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return eq(RHS); } - inline bool operator==(int64_t RHS) const { - return isSameValue(*this, APSInt(APInt(64, RHS), true)); - } inline bool operator!=(const APSInt& RHS) const { return !((*this) == RHS); } - inline bool operator!=(int64_t RHS) const { - return !((*this) == RHS); + + bool operator==(int64_t RHS) const { + return compareValues(*this, get(RHS)) == 0; + } + bool operator!=(int64_t RHS) const { + return compareValues(*this, get(RHS)) != 0; + } + bool operator<=(int64_t RHS) const { + return compareValues(*this, get(RHS)) <= 0; + } + bool operator>=(int64_t RHS) const { + return compareValues(*this, get(RHS)) >= 0; + } + bool operator<(int64_t RHS) const { + return compareValues(*this, get(RHS)) < 0; + } + bool operator>(int64_t RHS) const { + return compareValues(*this, get(RHS)) > 0; } // The remaining operators just wrap the logic of APInt, but retain the @@ -260,37 +279,49 @@ public: /// \brief Determine if two APSInts have the same value, zero- or /// sign-extending as needed. static bool isSameValue(const APSInt &I1, const APSInt &I2) { + return !compareValues(I1, I2); + } + + /// \brief Compare underlying values of two numbers. + static int compareValues(const APSInt &I1, const APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) - return I1 == I2; + return I1 == I2 ? 0 : I1 > I2 ? 1 : -1; // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) - return isSameValue(I1, I2.extend(I1.getBitWidth())); + return compareValues(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) - return isSameValue(I1.extend(I2.getBitWidth()), I2); - - assert(I1.isSigned() != I2.isSigned()); + return compareValues(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Check for negative values and do an - // unsigned compare if signs match. - if ((I1.isSigned() && I1.isNegative()) || - (!I1.isSigned() && I2.isNegative())) - return false; + // unsigned compare if both are positive. + if (I1.isSigned()) { + assert(!I2.isSigned() && "Expected signed mismatch"); + if (I1.isNegative()) + return -1; + } else { + assert(I2.isSigned() && "Expected signed mismatch"); + if (I2.isNegative()) + return 1; + } - return I1.eq(I2); + return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1; } + static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } + static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } + /// Profile - Used to insert APSInt objects, or objects that contain APSInt /// objects, into FoldingSets. void Profile(FoldingSetNodeID& ID) const; }; -inline bool operator==(int64_t V1, const APSInt& V2) { - return V2 == V1; -} -inline bool operator!=(int64_t V1, const APSInt& V2) { - return V2 != V1; -} +inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } +inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } +inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } +inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } +inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } +inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { I.print(OS, I.isSigned()); diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 8c14a42..5b7ed9c 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -97,12 +97,10 @@ namespace llvm { /*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 /// Construct an ArrayRef from ArrayRef. This uses SFINAE to /// ensure that only ArrayRefs of pointers can be converted. diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 34e2284..0dbe810 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -29,6 +29,9 @@ class BitVector { enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, + "Unsupported word size"); + BitWord *Bits; // Actual bits. unsigned Size; // Size of bitvector in bits. unsigned Capacity; // Size of allocated memory in BitWord. @@ -118,12 +121,7 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32((uint32_t)Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } @@ -157,13 +155,8 @@ public: /// of the bits are set. int find_first() const { for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -180,23 +173,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -239,6 +222,7 @@ public: } BitVector &set(unsigned Idx) { + assert(Bits && "Bits never allocated"); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -450,6 +434,7 @@ public: // Grow the bitvector to have enough elements. Capacity = RHSWords; + assert(Capacity > 0 && "negative capacity?"); BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); @@ -545,6 +530,7 @@ private: void grow(unsigned NewSize) { Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + assert(Capacity > 0 && "realloc-ing zero space"); Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); @@ -556,7 +542,7 @@ private: template void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size."); + static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); MaskWords = std::min(MaskWords, (size() + 31) / 32); const unsigned Scale = BITWORD_SIZE / 32; unsigned i; diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index c44b67a..1699ea3 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -31,26 +31,35 @@ namespace llvm { -template, - bool IsConst = false> +namespace detail { +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template +struct DenseMapPair : public std::pair { + KeyT &getFirst() { return std::pair::first; } + const KeyT &getFirst() const { return std::pair::first; } + ValueT &getSecond() { return std::pair::second; } + const ValueT &getSecond() const { return std::pair::second; } +}; +} + +template < + typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, + typename Bucket = detail::DenseMapPair, bool IsConst = false> class DenseMapIterator; -template +template class DenseMapBase { -protected: - typedef std::pair BucketT; - public: typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; - typedef DenseMapIterator iterator; - typedef DenseMapIterator const_iterator; + typedef DenseMapIterator iterator; + typedef DenseMapIterator + const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); @@ -88,12 +97,12 @@ public: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey)) { - if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { - P->second.~ValueT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); decrementNumEntries(); } - P->first = EmptyKey; + P->getFirst() = EmptyKey; } } assert(getNumEntries() == 0 && "Node count imbalance!"); @@ -144,7 +153,7 @@ public: ValueT lookup(const KeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return TheBucket->second; + return TheBucket->getSecond(); return ValueT(); } @@ -191,16 +200,16 @@ public: if (!LookupBucketFor(Val, TheBucket)) return false; // not in map. - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); return true; } void erase(iterator I) { BucketT *TheBucket = &*I; - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); } @@ -250,10 +259,10 @@ protected: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); } #ifndef NDEBUG @@ -269,7 +278,7 @@ protected: "# initial buckets must be a power of two!"); const KeyT EmptyKey = getEmptyKey(); for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) - new (&B->first) KeyT(EmptyKey); + new (&B->getFirst()) KeyT(EmptyKey); } void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { @@ -279,21 +288,21 @@ protected: const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { // Insert the key/value into the new table. BucketT *DestBucket; - bool FoundVal = LookupBucketFor(B->first, DestBucket); + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); - DestBucket->first = std::move(B->first); - new (&DestBucket->second) ValueT(std::move(B->second)); + DestBucket->getFirst() = std::move(B->getFirst()); + new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); incrementNumEntries(); // Free the value. - B->second.~ValueT(); + B->getSecond().~ValueT(); } - B->first.~KeyT(); + B->getFirst().~KeyT(); } #ifndef NDEBUG @@ -304,7 +313,8 @@ protected: } template - void copyFrom(const DenseMapBase& other) { + void copyFrom( + const DenseMapBase &other) { assert(&other != this); assert(getNumBuckets() == other.getNumBuckets()); @@ -316,10 +326,12 @@ protected: getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { - new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); - if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && - !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) - new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); + new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); } } @@ -396,8 +408,8 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(Value); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(Value); return TheBucket; } @@ -405,16 +417,16 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = std::move(Key); - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = std::move(Key); + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } @@ -430,11 +442,12 @@ private: // causing infinite loops in lookup. unsigned NewNumEntries = getNumEntries() + 1; unsigned NumBuckets = getNumBuckets(); - if (NewNumEntries*4 >= NumBuckets*3) { + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= + NumBuckets/8)) { this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } @@ -446,7 +459,7 @@ private: // If we are writing over a tombstone, remember this. const KeyT EmptyKey = getEmptyKey(); - if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) decrementNumTombstones(); return TheBucket; @@ -480,14 +493,14 @@ private: while (1) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. - if (KeyInfoT::isEqual(Val, ThisBucket->first)) { + if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { FoundBucket = ThisBucket; return true; } // If we found an empty bucket, the key doesn't exist in the set. // Insert it and return the default value. - if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; @@ -496,7 +509,8 @@ private: // If this is a tombstone, remember it. If Val ends up not in the map, we // prefer to return it than something that would require more probing. - if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) FoundTombstone = ThisBucket; // Remember the first tombstone found. // Otherwise, it's a hash collision or a tombstone, continue quadratic @@ -525,16 +539,15 @@ public: } }; -template > -class DenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { +template , + typename BucketT = detail::DenseMapPair> +class DenseMap : public DenseMapBase, + KeyT, ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; BucketT *Buckets; unsigned NumEntries; @@ -677,17 +690,17 @@ private: } }; -template > +template , + typename BucketT = detail::DenseMapPair> class SmallDenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { + : public DenseMapBase< + SmallDenseMap, KeyT, + ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; unsigned Small : 1; unsigned NumEntries : 31; @@ -744,23 +757,23 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *LHSB = &getInlineBuckets()[i], *RHSB = &RHS.getInlineBuckets()[i]; - bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && - !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); - bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && - !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); if (hasLHSValue && hasRHSValue) { // Swap together if we can... std::swap(*LHSB, *RHSB); continue; } // Swap separately and handle any assymetry. - std::swap(LHSB->first, RHSB->first); + std::swap(LHSB->getFirst(), RHSB->getFirst()); if (hasLHSValue) { - new (&RHSB->second) ValueT(std::move(LHSB->second)); - LHSB->second.~ValueT(); + new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); } else if (hasRHSValue) { - new (&LHSB->second) ValueT(std::move(RHSB->second)); - RHSB->second.~ValueT(); + new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); } } return; @@ -785,12 +798,12 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *NewB = &LargeSide.getInlineBuckets()[i], *OldB = &SmallSide.getInlineBuckets()[i]; - new (&NewB->first) KeyT(std::move(OldB->first)); - OldB->first.~KeyT(); - if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && - !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { - new (&NewB->second) ValueT(std::move(OldB->second)); - OldB->second.~ValueT(); + new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); } } @@ -852,16 +865,16 @@ public: const KeyT EmptyKey = this->getEmptyKey(); const KeyT TombstoneKey = this->getTombstoneKey(); for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && "Too many inline buckets!"); - new (&TmpEnd->first) KeyT(std::move(P->first)); - new (&TmpEnd->second) ValueT(std::move(P->second)); + new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); ++TmpEnd; - P->second.~ValueT(); + P->getSecond().~ValueT(); } - P->first.~KeyT(); + P->getFirst().~KeyT(); } // Now make this map use the large rep, and move all the entries back @@ -972,13 +985,12 @@ private: } }; -template +template class DenseMapIterator { - typedef std::pair Bucket; - typedef DenseMapIterator ConstIterator; - friend class DenseMapIterator; + typedef DenseMapIterator ConstIterator; + friend class DenseMapIterator; + public: typedef ptrdiff_t difference_type; typedef typename std::conditional::type @@ -999,9 +1011,9 @@ public: // If IsConst is true this is a converting constructor from iterator to // const_iterator and the default copy constructor is used. // Otherwise this is a copy constructor for iterator. - DenseMapIterator(const DenseMapIterator& I) - : Ptr(I.Ptr), End(I.End) {} + DenseMapIterator( + const DenseMapIterator &I) + : Ptr(I.Ptr), End(I.End) {} reference operator*() const { return *Ptr; @@ -1031,9 +1043,8 @@ private: const KeyT Empty = KeyInfoT::getEmptyKey(); const KeyT Tombstone = KeyInfoT::getTombstoneKey(); - while (Ptr != End && - (KeyInfoT::isEqual(Ptr->first, Empty) || - KeyInfoT::isEqual(Ptr->first, Tombstone))) + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) ++Ptr; } }; diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 9ab1be2..d340240 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -18,13 +18,29 @@ namespace llvm { +namespace detail { +struct DenseSetEmpty {}; + +// Use the empty base class trick so we can create a DenseMap where the buckets +// contain only a single item. +template class DenseSetPair : public DenseSetEmpty { + KeyT key; + +public: + KeyT &getFirst() { return key; } + const KeyT &getFirst() const { return key; } + DenseSetEmpty &getSecond() { return *this; } + const DenseSetEmpty &getSecond() const { return *this; } +}; +} + /// DenseSet - This implements a dense probed hash-table based set. -/// -/// FIXME: This is currently implemented directly in terms of DenseMap, this -/// should be optimized later if there is a need. template > class DenseSet { - typedef DenseMap MapTy; + typedef DenseMap> MapTy; + static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), + "DenseMap buckets unexpectedly large!"); MapTy TheMap; public: typedef ValueT key_type; @@ -72,8 +88,8 @@ public: Iterator(const typename MapTy::iterator &i) : I(i) {} - ValueT& operator*() { return I->first; } - ValueT* operator->() { return &I->first; } + ValueT &operator*() { return I->getFirst(); } + ValueT *operator->() { return &I->getFirst(); } Iterator& operator++() { ++I; return *this; } bool operator==(const Iterator& X) const { return I == X.I; } @@ -92,8 +108,8 @@ public: ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} - const ValueT& operator*() { return I->first; } - const ValueT* operator->() { return &I->first; } + const ValueT &operator*() { return I->getFirst(); } + const ValueT *operator->() { return &I->getFirst(); } ConstIterator& operator++() { ++I; return *this; } bool operator==(const ConstIterator& X) const { return I == X.I; } @@ -129,7 +145,8 @@ public: void erase(ConstIterator CI) { return TheMap.erase(CI.I); } std::pair insert(const ValueT &V) { - return TheMap.insert(std::make_pair(V, 0)); + detail::DenseSetEmpty Empty; + return TheMap.insert(std::make_pair(V, Empty)); } // Range insertion of values. diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 0f69146..6cd9e68 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -33,10 +33,10 @@ #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H #define LLVM_ADT_DEPTHFIRSTITERATOR_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include #include diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index e0396c7..d6a26f8 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -17,6 +17,7 @@ #include "llvm/Support/DataTypes.h" #include +#include #include namespace llvm { @@ -254,7 +255,7 @@ public: assert(Node != nullptr && "Dereferencing end()!"); return Node->getData(); } - reference operator->() const { return operator*(); } + pointer operator->() const { return &operator*(); } member_iterator &operator++() { assert(Node != nullptr && "++'d off the end of the list!"); diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 14c5933..7ade167 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" @@ -532,46 +533,6 @@ public: }; //===----------------------------------------------------------------------===// -/// FoldingSetVectorIterator - This implements an iterator for -/// FoldingSetVector. It is only necessary because FoldingSetIterator provides -/// a value_type of T, while the vector in FoldingSetVector exposes -/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very -/// much besides operator* and operator->, so we just wrap the inner vector -/// iterator and perform the extra dereference. -template -class FoldingSetVectorIterator { - // Provide a typedef to workaround the lack of correct injected class name - // support in older GCCs. - typedef FoldingSetVectorIterator SelfT; - - VectorIteratorT Iterator; - -public: - FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {} - - bool operator==(const SelfT &RHS) const { - return Iterator == RHS.Iterator; - } - bool operator!=(const SelfT &RHS) const { - return Iterator != RHS.Iterator; - } - - T &operator*() const { return **Iterator; } - - T *operator->() const { return *Iterator; } - - inline SelfT &operator++() { - ++Iterator; - return *this; - } - SelfT operator++(int) { - SelfT tmp = *this; - ++*this; - return tmp; - } -}; - -//===----------------------------------------------------------------------===// /// FoldingSetVector - This template class combines a FoldingSet and a vector /// to provide the interface of FoldingSet but with deterministic iteration /// order based on the insertion order. T must be a subclass of FoldingSetNode @@ -586,12 +547,11 @@ public: : Set(Log2InitSize) { } - typedef FoldingSetVectorIterator iterator; + typedef pointee_iterator iterator; iterator begin() { return Vector.begin(); } iterator end() { return Vector.end(); } - typedef FoldingSetVectorIterator - const_iterator; + typedef pointee_iterator const_iterator; const_iterator begin() const { return Vector.begin(); } const_iterator end() const { return Vector.end(); } @@ -735,31 +695,9 @@ template class FoldingSetNodeWrapper : public FoldingSetNode { T data; public: - explicit FoldingSetNodeWrapper(const T &x) : data(x) {} - virtual ~FoldingSetNodeWrapper() {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1) - : data(a1) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2) - : data(a1,a2) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3) - : data(a1,a2,a3) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4) - : data(a1,a2,a3,a4) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4, const A5 &a5) - : data(a1,a2,a3,a4,a5) {} - + template + explicit FoldingSetNodeWrapper(Ts &&... Args) + : data(std::forward(Args)...) {} void Profile(FoldingSetNodeID &ID) { FoldingSetTrait::Profile(data, ID); } diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index abf02b8..a1e7864 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -55,12 +55,6 @@ #include #include -// Allow detecting C++11 feature availability when building with Clang without -// breaking other compilers. -#ifndef __has_feature -# define __has_feature(x) 0 -#endif - namespace llvm { /// \brief An opaque object representing a hash code. @@ -553,8 +547,6 @@ public: return buffer_ptr; } -#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__) - /// \brief Recursive, variadic combining method. /// /// This function recurses through each argument, combining that argument @@ -568,53 +560,6 @@ public: return combine(length, buffer_ptr, buffer_end, args...); } -#else - // Manually expanded recursive combining methods. See variadic above for - // documentation. - - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end); - } - -#endif - /// \brief Base case for recursive, variadic combining. /// /// The base case when combining arguments recursively is reached when all @@ -643,9 +588,6 @@ public: } // namespace detail } // namespace hashing - -#if __has_feature(__cxx_variadic_templates__) - /// \brief Combine values into a single hash_code. /// /// This routine accepts a varying number of arguments of any type. It will @@ -663,52 +605,6 @@ template hash_code hash_combine(const Ts &...args) { return helper.combine(0, helper.buffer, helper.buffer + 64, args...); } -#else - -// What follows are manually exploded overloads for each argument width. See -// the above variadic definition for documentation and specification. - -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5, arg6); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2); -} -template -hash_code hash_combine(const T1 &arg1) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1); -} - -#endif - - // Implementation details for implementations of hash_value overloads provided // here. namespace hashing { diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 7f0c239..748d3e4 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -33,8 +33,8 @@ class ImmutableListImpl : public FoldingSetNode { friend class ImmutableListFactory; - void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; - ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; + void operator=(const ImmutableListImpl&) = delete; + ImmutableListImpl(const ImmutableListImpl&) = delete; public: const T& getHead() const { return Head; } diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 11f281b..75fee90 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -122,8 +122,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; bool contains(key_type_ref K) const { diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 5a3d8ad..3c6f58c 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -1014,8 +1014,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; friend class Factory; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 46549ee..99be38f 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. - LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } + explicit operator bool() const { return pip.getOpaqueValue(); } /// NodeRef - Create a reference to the node p with n elements. template diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index c859c98..9b12d04 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -84,7 +84,7 @@ namespace llvm { friend struct IntrusiveRefCntPtrInfo; }; - + template struct IntrusiveRefCntPtrInfo { static void retain(T *obj) { obj->Retain(); } static void release(T *obj) { obj->Release(); } @@ -114,7 +114,7 @@ public: delete static_cast(this); } }; - + //===----------------------------------------------------------------------===// /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" /// that assumes the wrapped object has a reference count associated @@ -177,7 +177,7 @@ public: T* get() const { return Obj; } - LLVM_EXPLICIT operator bool() const { return Obj; } + explicit operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 14c49c5..1331b15 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -18,6 +18,7 @@ #define LLVM_ADT_MAPVECTOR_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include namespace llvm { @@ -181,6 +182,14 @@ void MapVector::remove_if(Function Pred) { Vector.erase(O, Vector.end()); } +/// \brief A MapVector that performs no allocations if smaller than a certain +/// size. +template +struct SmallMapVector + : MapVector, + SmallVector, N>> { +}; + } // end namespace llvm #endif diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h index 5793bd2..d69ec17 100644 --- a/include/llvm/ADT/None.h +++ b/include/llvm/ADT/None.h @@ -19,9 +19,8 @@ namespace llvm { /// \brief A simple null object to allow implicit construction of Optional /// and similar types without having to spell out the specialization's name. -enum NoneType { - None -}; +enum class NoneType { None }; +const NoneType None = None; } #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 591872e..855ab89 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -70,8 +70,6 @@ public: return *this; } -#if LLVM_HAS_VARIADIC_TEMPLATES - /// Create a new object by constructing it in place with the given arguments. template void emplace(ArgTypes &&...Args) { @@ -80,51 +78,6 @@ public: new (storage.buffer) T(std::forward(Args)...); } -#else - - /// Create a new object by default-constructing it in place. - void emplace() { - reset(); - hasVal = true; - new (storage.buffer) T(); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2, T3 &&A3) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2), - std::forward(A3)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2), - std::forward(A3), std::forward(A4)); - } - -#endif // LLVM_HAS_VARIADIC_TEMPLATES - static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -168,7 +121,7 @@ public: const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } - LLVM_EXPLICIT operator bool() const { return hasVal; } + explicit operator bool() const { return hasVal; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } T* operator->() { return getPointer(); } diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index a6dddd2..f27b811 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -61,7 +61,7 @@ namespace llvm { NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv }; }; - + /// PointerUnion - This implements a discriminated union of two pointer types, /// and keeps the discriminator bit-mangled into the low bits of the pointer. /// This allows the implementation to be extremely efficient in space, but @@ -80,7 +80,7 @@ namespace llvm { template class PointerUnion { public: - typedef PointerIntPair > ValTy; private: ValTy Val; @@ -96,14 +96,14 @@ namespace llvm { public: PointerUnion() {} - + PointerUnion(PT1 V) : Val( const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))) { } PointerUnion(PT2 V) : Val( const_cast(PointerLikeTypeTraits::getAsVoidPointer(V)), 1) { } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { @@ -111,7 +111,7 @@ namespace llvm { // we recursively strip off low bits if we have a nested PointerUnion. return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } + explicit operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -123,7 +123,7 @@ namespace llvm { int TyNo = Ty::Num; return static_cast(Val.getInt()) == TyNo; } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -131,7 +131,7 @@ namespace llvm { assert(is() && "Invalid accessor called"); return PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -160,7 +160,7 @@ namespace llvm { Val.initWithPointer(nullptr); return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion &operator=(const PT1 &RHS) { @@ -174,7 +174,7 @@ namespace llvm { 1); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion getFromOpaqueValue(void *VP) { PointerUnion V; @@ -195,6 +195,12 @@ namespace llvm { 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 @@ -208,16 +214,16 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; }; - - + + /// PointerUnion3 - This is a pointer union of three pointer types. See /// documentation for PointerUnion for usage. template @@ -233,7 +239,7 @@ namespace llvm { IsInnerUnion(ValTy val) : Val(val) { } template int is() const { - return Val.template is() && + return Val.template is() && Val.template get().template is(); } template @@ -257,7 +263,7 @@ namespace llvm { public: PointerUnion3() {} - + PointerUnion3(PT1 V) { Val = InnerUnion(V); } @@ -267,12 +273,12 @@ namespace llvm { PointerUnion3(PT3 V) { Val = V; } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is() return true if the Union currently holds the type matching T. template int is() const { @@ -283,7 +289,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template is(); } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -296,7 +302,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template get(); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -310,7 +316,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion3 &operator=(const PT1 &RHS) { @@ -325,7 +331,7 @@ namespace llvm { Val = RHS; return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion3 getFromOpaqueValue(void *VP) { PointerUnion3 V; @@ -333,7 +339,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template @@ -347,10 +353,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion3::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; @@ -368,7 +374,7 @@ namespace llvm { ValTy Val; public: PointerUnion4() {} - + PointerUnion4(PT1 V) { Val = InnerUnion1(V); } @@ -381,12 +387,12 @@ namespace llvm { PointerUnion4(PT4 V) { Val = InnerUnion2(V); } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is() return true if the Union currently holds the type matching T. template int is() const { @@ -395,10 +401,10 @@ namespace llvm { ::llvm::PointerUnionTypeSelector >::Return Ty; - return Val.template is() && + return Val.template is() && Val.template get().template is(); } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -411,7 +417,7 @@ namespace llvm { >::Return Ty; return Val.template get().template get(); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -425,7 +431,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion4 &operator=(const PT1 &RHS) { @@ -444,7 +450,7 @@ namespace llvm { Val = InnerUnion2(RHS); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion4 getFromOpaqueValue(void *VP) { PointerUnion4 V; @@ -452,7 +458,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template @@ -466,10 +472,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion4::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 4e56e4d..57af18e 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -18,6 +18,7 @@ #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" +#include #include // for std::size_t #include // for qsort #include @@ -63,8 +64,6 @@ struct greater_ptr : public std::binary_function { /// a function_ref. template class function_ref; -#if LLVM_HAS_VARIADIC_TEMPLATES - template class function_ref { Ret (*callback)(intptr_t callable, Params ...params); @@ -89,112 +88,6 @@ public: } }; -#else - -template -class function_ref { - Ret (*callback)(intptr_t callable); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable) { - return (*reinterpret_cast(callable))(); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()() const { return callback(callable); } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1) { - return (*reinterpret_cast(callable))( - std::forward(param1)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1) { - return callback(callable, std::forward(param1)); - } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2) { - return callback(callable, - std::forward(param1), - std::forward(param2)); - } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2, - Param3 param3) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2, Param3 param3) { - return callback(callable, - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } -}; - -#endif - // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // @@ -301,6 +194,28 @@ struct less_second { } }; +// A subset of N3658. More stuff can be added as-needed. + +/// \brief Represents a compile-time sequence of integers. +template struct integer_sequence { + typedef T value_type; + + static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } +}; + +/// \brief Alias for the common case of a sequence of size_ts. +template +struct index_sequence : integer_sequence {}; + +template +struct build_index_impl : build_index_impl {}; +template +struct build_index_impl<0, I...> : index_sequence {}; + +/// \brief Creates a compile-time integer sequence for a parameter pack. +template +struct index_sequence_for : build_index_impl {}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -392,8 +307,6 @@ void DeleteContainerSeconds(Container &C) { // Extra additions to //===----------------------------------------------------------------------===// -#if LLVM_HAS_VARIADIC_TEMPLATES - // Implement make_unique according to N3656. /// \brief Constructs a `new T()` with the given args and returns a @@ -427,123 +340,7 @@ make_unique(size_t n) { /// This function isn't used and is only here to provide better compile errors. template typename std::enable_if::value != 0>::type -make_unique(Args &&...) LLVM_DELETED_FUNCTION; - -#else - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique() { - return std::unique_ptr(new T()); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1) { - return std::unique_ptr(new T(std::forward(arg1))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { - return std::unique_ptr(new T(std::forward(arg1), - std::forward(arg2), - std::forward(arg3))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8), - std::forward(arg9))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8), - std::forward(arg9), std::forward(arg10))); -} - -template -typename std::enable_if::value &&std::extent::value == 0, - std::unique_ptr>::type -make_unique(size_t n) { - return std::unique_ptr(new typename std::remove_extent::type[n]()); -} - -#endif +make_unique(Args &&...) = delete; struct FreeDeleter { void operator()(void* v) { @@ -558,6 +355,35 @@ struct pair_hash { } }; +/// A functor like C++14's std::less in its absence. +struct less { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) < std::forward(b); + } +}; + +/// A functor like C++14's std::equal in its absence. +struct equal { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) == std::forward(b); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template struct deref { + T func; + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 2f60ecc..5abe76c 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -90,8 +90,8 @@ class ScopedHashTableScope { /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. ScopedHashTableVal *LastValInScope; - void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; - ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + void operator=(ScopedHashTableScope&) = delete; + ScopedHashTableScope(ScopedHashTableScope&) = delete; public: ScopedHashTableScope(ScopedHashTable &HT); ~ScopedHashTableScope(); diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index ababf0f..22e8ccd 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -53,6 +53,9 @@ class SmallBitVector { SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits }; + static_assert(NumBaseBits == 64 || NumBaseBits == 32, + "Unsupported word size"); + public: typedef unsigned size_type; // Encapsulation of a single bit. @@ -177,11 +180,7 @@ public: size_type count() const { if (isSmall()) { uintptr_t Bits = getSmallBits(); - if (NumBaseBits == 32) - return CountPopulation_32(Bits); - if (NumBaseBits == 64) - return CountPopulation_64(Bits); - llvm_unreachable("Unsupported!"); + return countPopulation(Bits); } return getPointer()->count(); } @@ -214,11 +213,7 @@ public: uintptr_t Bits = getSmallBits(); if (Bits == 0) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_first(); } @@ -232,11 +227,7 @@ public: Bits &= ~uintptr_t(0) << (Prev + 1); if (Bits == 0 || Prev + 1 >= getSmallSize()) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_next(Prev); } @@ -292,8 +283,12 @@ public: } SmallBitVector &set(unsigned Idx) { - if (isSmall()) + if (isSmall()) { + assert(Idx <= static_cast( + std::numeric_limits::digits) && + "undefined behavior"); setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + } else getPointer()->set(Idx); return *this; @@ -556,7 +551,6 @@ public: private: template void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size"); if (NumBaseBits == 64 && MaskWords >= 2) { uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32); if (InvertMask) M = ~M; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index b8977fa..3e3c9c1 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -132,7 +132,7 @@ private: /// Grow - Allocate a larger backing store for the buckets and move it over. void Grow(unsigned NewSize); - void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION; + void operator=(const SmallPtrSetImplBase &RHS) = delete; protected: /// swap - Swaps the elements of two sets. /// Note: This method assumes that both sets have the same small size. @@ -242,7 +242,7 @@ template class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits PtrTraits; - SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION; + SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; protected: // Constructors that forward to the base. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) @@ -257,8 +257,10 @@ public: typedef SmallPtrSetIterator iterator; typedef SmallPtrSetIterator const_iterator; - /// insert - This returns true if the pointer was new to the set, false if it - /// was already in the set. + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. The bool component of the returned pair is true if and only if the + /// insertion takes place, and the iterator component of the pair points to + /// the element equal to Ptr. std::pair insert(PtrType Ptr) { auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 2117541..14e2c7b 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -135,11 +135,11 @@ public: const_pointer data() const { return const_pointer(begin()); } reference operator[](size_type idx) { - assert(begin() + idx < end()); + assert(idx < size()); return begin()[idx]; } const_reference operator[](size_type idx) const { - assert(begin() + idx < end()); + assert(idx < size()); return begin()[idx]; } @@ -307,8 +307,11 @@ protected: /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. - template - static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { + template + static void uninitialized_copy( + T1 *I, T1 *E, T2 *Dest, + typename std::enable_if::type, + T2>::value>::type * = nullptr) { // Use memcpy for PODs iterated by pointers (which includes SmallVector // iterators): std::uninitialized_copy optimizes to memmove, but we can // use memcpy here. @@ -340,7 +343,7 @@ template class SmallVectorImpl : public SmallVectorTemplateBase::value> { typedef SmallVectorTemplateBase::value > SuperClass; - SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION; + SmallVectorImpl(const SmallVectorImpl&) = delete; public: typedef typename SuperClass::iterator iterator; typedef typename SuperClass::size_type size_type; @@ -367,7 +370,7 @@ public: this->EndX = this->BeginX; } - void resize(unsigned N) { + void resize(size_type N) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -380,7 +383,7 @@ public: } } - void resize(unsigned N, const T &NV) { + void resize(size_type N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -392,7 +395,7 @@ public: } } - void reserve(unsigned N) { + void reserve(size_type N) { if (this->capacity() < N) this->grow(N); } @@ -414,9 +417,7 @@ public: this->grow(this->size()+NumInputs); // Copy the new elements over. - // TODO: NEED To compile time dispatch on whether in_iter is a random access - // iterator to use the fast uninitialized_copy. - std::uninitialized_copy(in_start, in_end, this->end()); + this->uninitialized_copy(in_start, in_end, this->end()); this->setEnd(this->end() + NumInputs); } @@ -431,7 +432,7 @@ public: this->setEnd(this->end() + NumInputs); } - void assign(unsigned NumElts, const T &Elt) { + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) this->grow(NumElts); @@ -537,7 +538,7 @@ public: assert(I <= this->end() && "Inserting past the end of the vector."); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -591,7 +592,7 @@ public: size_t NumToInsert = std::distance(From, To); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -632,6 +633,13 @@ public: return I; } + template void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward(Args)...); + this->setEnd(this->end() + 1); + } + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); SmallVectorImpl &operator=(SmallVectorImpl &&RHS); @@ -658,7 +666,7 @@ public: /// of the buffer when they know that more elements are available, and only /// update the size later. This avoids the cost of value initializing elements /// which will only be overwritten. - void set_size(unsigned N) { + void set_size(size_type N) { assert(N <= this->capacity()); this->setEnd(this->begin() + N); } @@ -684,7 +692,7 @@ void SmallVectorImpl::swap(SmallVectorImpl &RHS) { // Swap the shared elements. size_t NumShared = this->size(); if (NumShared > RHS.size()) NumShared = RHS.size(); - for (unsigned i = 0; i != static_cast(NumShared); ++i) + for (size_type i = 0; i != NumShared; ++i) std::swap((*this)[i], RHS[i]); // Copy over the extra elts. @@ -841,7 +849,7 @@ public: SmallVector() : SmallVectorImpl(N) { } - explicit SmallVector(unsigned Size, const T &Value = T()) + explicit SmallVector(size_t Size, const T &Value = T()) : SmallVectorImpl(N) { this->assign(Size, Value); } @@ -876,6 +884,17 @@ public: SmallVectorImpl::operator=(::std::move(RHS)); return *this; } + + SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { + if (!RHS.empty()) + SmallVectorImpl::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVectorImpl &&RHS) { + SmallVectorImpl::operator=(::std::move(RHS)); + return *this; + } + }; template diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index d5bde29..20cbe2c 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -124,25 +124,15 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32(Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } /// find_first - Returns the index of the first set bit. int find_first() const { for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Illegal empty element"); } @@ -161,23 +151,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index f858536..e3aa258 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -133,8 +133,8 @@ class SparseMultiSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION; - SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION; + SparseMultiSet(const SparseMultiSet&) = delete; + SparseMultiSet &operator=(const SparseMultiSet&) = delete; /// Whether the given entry is the head of the list. List heads's previous /// pointers are to the tail of the list, allowing for efficient access to the diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 9a13440..a45d1c8 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -133,8 +133,8 @@ class SparseSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION; - SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION; + SparseSet(const SparseSet&) = delete; + SparseSet &operator=(const SparseSet&) = delete; public: typedef ValueT value_type; diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 2feb2ab..8721c73 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -111,7 +111,7 @@ public: /// and data. template class StringMapEntry : public StringMapEntryBase { - StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; + StringMapEntry(StringMapEntry &E) = delete; public: ValueTy second; @@ -179,19 +179,6 @@ public: return Create(Key, ValueTy()); } - /// GetStringMapEntryFromValue - Given a value that is known to be embedded - /// into a StringMapEntry, return the StringMapEntry itself. - static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { - StringMapEntry *EPtr = 0; - char *Ptr = reinterpret_cast(&V) - - (reinterpret_cast(&EPtr->second) - - reinterpret_cast(EPtr)); - return *reinterpret_cast(Ptr); - } - static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { - return GetStringMapEntryFromValue(const_cast(V)); - } - /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded /// into a StringMapEntry, return the StringMapEntry itself. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 778fa10..6111c42 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -91,6 +91,13 @@ namespace llvm { iterator end() const { return Data + Length; } + const unsigned char *bytes_begin() const { + return reinterpret_cast(begin()); + } + const unsigned char *bytes_end() const { + return reinterpret_cast(end()); + } + /// @} /// @name String Operations /// @{ diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index e158f9d..f29608f 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -27,9 +27,12 @@ class TinyPtrVector { public: typedef llvm::SmallVector VecTy; typedef typename VecTy::value_type value_type; + typedef llvm::PointerUnion PtrUnion; - llvm::PointerUnion Val; +private: + PtrUnion Val; +public: TinyPtrVector() {} ~TinyPtrVector() { if (VecTy *V = Val.template dyn_cast()) @@ -96,6 +99,14 @@ public: return *this; } + /// Constructor from an ArrayRef. + /// + /// This also is a constructor for individual array elements due to the single + /// element constructor for ArrayRef. + explicit TinyPtrVector(ArrayRef Elts) + : Val(Elts.size() == 1 ? PtrUnion(Elts[0]) + : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {} + // implicit conversion operator to ArrayRef. operator ArrayRef() const { if (Val.isNull()) @@ -105,6 +116,15 @@ public: return *Val.template get(); } + // implicit conversion operator to MutableArrayRef. + operator MutableArrayRef() { + if (Val.isNull()) + return None; + if (Val.template is()) + return *Val.getAddrOfPtr1(); + return *Val.template get(); + } + bool empty() const { // This vector can be empty if it contains no element, or if it // contains a pointer to an empty vector. diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index fbc19f8..886f6fb 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -50,6 +50,7 @@ public: armeb, // ARM (big endian): armeb aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be + bpf, // eBPF or extended BPF or 64-bit BPF (little endian) hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel @@ -60,6 +61,7 @@ public: ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 systemz, // SystemZ: s390x @@ -138,7 +140,9 @@ public: Bitrig, AIX, CUDA, // NVIDIA CUDA - NVCL // NVIDIA OpenCL + NVCL, // NVIDIA OpenCL + AMDHSA, // AMD HSA Runtime + PS4 }; enum EnvironmentType { UnknownEnvironment, @@ -198,6 +202,13 @@ public: Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, const Twine &EnvironmentStr); + bool operator==(const Triple &Other) const { + return Arch == Other.Arch && SubArch == Other.SubArch && + Vendor == Other.Vendor && OS == Other.OS && + Environment == Other.Environment && + ObjectFormat == Other.ObjectFormat; + } + /// @} /// @name Normalization /// @{ @@ -208,6 +219,9 @@ public: /// common case in which otherwise valid components are in the wrong order. static std::string normalize(StringRef Str); + /// \brief Return the normalized form of this triple's string. + std::string normalize() const { return normalize(Data); } + /// @} /// @name Typed Component Access /// @{ @@ -332,6 +346,12 @@ public: return false; } + bool isOSVersionLT(const Triple &Other) const { + unsigned RHS[3]; + Other.getOSVersion(RHS[0], RHS[1], RHS[2]); + return isOSVersionLT(RHS[0], RHS[1], RHS[2]); + } + /// isMacOSXVersionLT - Comparison function for checking OS X version /// compatibility, which handles supporting skewed version numbering schemes /// used by the "darwin" triples. @@ -364,10 +384,28 @@ public: return isMacOSX() || isiOS(); } + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + bool isOSFreeBSD() const { return getOS() == Triple::FreeBSD; } + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSBitrig() const { + return getOS() == Triple::Bitrig; + } + bool isWindowsMSVCEnvironment() const { return getOS() == Triple::Win32 && (getEnvironment() == Triple::UnknownEnvironment || @@ -403,7 +441,7 @@ public: /// \brief Tests whether the OS is Windows. bool isOSWindows() const { - return getOS() == Triple::Win32 || isOSCygMing(); + return getOS() == Triple::Win32; } /// \brief Tests whether the OS is NaCl (Native Client) @@ -431,6 +469,19 @@ public: return getObjectFormat() == Triple::MachO; } + /// \brief Tests whether the target is the PS4 CPU + bool isPS4CPU() const { + return getArch() == Triple::x86_64 && + getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// \brief Tests whether the target is the PS4 platform + bool isPS4() const { + return getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + /// @} /// @name Mutators /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 77d92b4..9e9a4e1 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -80,7 +80,7 @@ namespace llvm { /// StringRef) codegen as desired. class Twine { /// NodeKind - Represent the type of an argument. - enum NodeKind { + enum NodeKind : unsigned char { /// An empty string; the result of concatenating anything with it is also /// empty. NullKind, @@ -153,12 +153,10 @@ namespace llvm { /// RHS - The suffix in the concatenation, which may be uninitialized for /// Null or Empty kinds. Child RHS; - // enums stored as unsigned chars to save on space while some compilers - // don't support specifying the backing type for an enum /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char LHSKind; + NodeKind LHSKind; /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). - unsigned char RHSKind; + NodeKind RHSKind; private: /// Construct a nullary twine; the kind must be NullKind or EmptyKind. @@ -184,7 +182,7 @@ namespace llvm { /// Since the intended use of twines is as temporary objects, assignments /// when concatenating might cause undefined behavior or stack corruptions - Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION; + Twine &operator=(const Twine &Other) = delete; /// isNull - Check for the null twine. bool isNull() const { @@ -238,10 +236,10 @@ namespace llvm { } /// getLHSKind - Get the NodeKind of the left-hand side. - NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + NodeKind getLHSKind() const { return LHSKind; } /// getRHSKind - Get the NodeKind of the right-hand side. - NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + NodeKind getRHSKind() const { return RHSKind; } /// printOneChild - Print one child from a twine. void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 8c19a6f..a7b9306 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -237,14 +237,14 @@ public: // These are to catch errors when people try to use them as random access // iterators. template -void operator-(int, ilist_iterator) LLVM_DELETED_FUNCTION; +void operator-(int, ilist_iterator) = delete; template -void operator-(ilist_iterator,int) LLVM_DELETED_FUNCTION; +void operator-(ilist_iterator,int) = delete; template -void operator+(int, ilist_iterator) LLVM_DELETED_FUNCTION; +void operator+(int, ilist_iterator) = delete; template -void operator+(ilist_iterator,int) LLVM_DELETED_FUNCTION; +void operator+(ilist_iterator,int) = delete; // operator!=/operator== - Allow mixed comparisons without dereferencing // the iterator, which could very likely be pointing to end(). @@ -332,8 +332,8 @@ class iplist : public Traits { // No fundamental reason why iplist can't be copyable, but the default // copy/copy-assign won't do. - iplist(const iplist &) LLVM_DELETED_FUNCTION; - void operator=(const iplist &) LLVM_DELETED_FUNCTION; + iplist(const iplist &) = delete; + void operator=(const iplist &) = delete; public: typedef NodeTy *pointer; diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 56041db..e2c9e5e 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -10,8 +10,8 @@ #ifndef LLVM_ADT_ITERATOR_H #define LLVM_ADT_ITERATOR_H -#include #include +#include namespace llvm { diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index ecaf4a2..523a86f 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -32,7 +32,6 @@ class iterator_range { IteratorT begin_iterator, end_iterator; public: - iterator_range() {} iterator_range(IteratorT begin_iterator, IteratorT end_iterator) : begin_iterator(std::move(begin_iterator)), end_iterator(std::move(end_iterator)) {} diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 9bfa045..763f372 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -502,7 +502,7 @@ public: /// /// canBasicBlockModify - Return true if it is possible for execution of the - /// specified basic block to modify the value pointed to by Ptr. + /// specified basic block to modify the location Loc. bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); /// canBasicBlockModify - A convenience wrapper. @@ -510,17 +510,20 @@ public: return canBasicBlockModify(BB, Location(P, Size)); } - /// canInstructionRangeModify - Return true if it is possible for the - /// execution of the specified instructions to modify the value pointed to by - /// Ptr. The instructions to consider are all of the instructions in the - /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Location &Loc); - - /// canInstructionRangeModify - A convenience wrapper. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, uint64_t Size) { - return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + /// canInstructionRangeModRef - Return true if it is possible for the + /// execution of the specified instructions to mod\ref (according to the + /// mode) the location Loc. The instructions to consider are all + /// of the instructions in the range of [I1,I2] INCLUSIVE. + /// I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Location &Loc, + const ModRefResult Mode); + + /// canInstructionRangeModRef - A convenience wrapper. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Value *Ptr, + uint64_t Size, const ModRefResult Mode) { + return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 036d58d..afa7e6f 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -226,8 +226,8 @@ private: AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } - AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; - void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION; + AliasSet(const AliasSet &AS) = delete; + void operator=(const AliasSet &AS) = delete; PointerRec *getSomePointer() const { return PtrList; diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h new file mode 100644 index 0000000..fc1393f --- /dev/null +++ b/include/llvm/Analysis/AssumptionCache.h @@ -0,0 +1,183 @@ +//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that keeps track of @llvm.assume intrinsics in +// the functions of a module (allowing assumptions within any function to be +// found cheaply by other parts of the optimizer). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H +#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include + +namespace llvm { + +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + +/// \brief A cache of @llvm.assume calls within a function. +/// +/// This cache provides fast lookup of assumptions within a function by caching +/// them and amortizing the cost of scanning for them across all queries. The +/// cache is also conservatively self-updating so that it will never return +/// incorrect results about a function even as the function is being mutated. +/// However, flushing the cache and rebuilding it (or explicitly updating it) +/// may allow it to discover new assumptions. +class AssumptionCache { + /// \brief The function for which this cache is handling assumptions. + /// + /// We track this to lazily populate our assumptions. + Function &F; + + /// \brief Vector of weak value handles to calls of the @llvm.assume + /// intrinsic. + SmallVector AssumeHandles; + + /// \brief Flag tracking whether we have scanned the function yet. + /// + /// We want to be as lazy about this as possible, and so we scan the function + /// at the last moment. + bool Scanned; + + /// \brief Scan the function for assumptions and add them to the cache. + void scanFunction(); + +public: + /// \brief Construct an AssumptionCache from a function by scanning all of + /// its instructions. + AssumptionCache(Function &F) : F(F), Scanned(false) {} + + /// \brief Add an @llvm.assume intrinsic to this function's cache. + /// + /// The call passed in must be an instruction within this fuction and must + /// not already be in the cache. + void registerAssumption(CallInst *CI); + + /// \brief Clear the cache of @llvm.assume intrinsics for a function. + /// + /// It will be re-scanned the next time it is requested. + void clear() { + AssumeHandles.clear(); + Scanned = false; + } + + /// \brief Access the list of assumption handles currently tracked for this + /// fuction. + /// + /// Note that these produce weak handles that may be null. The caller must + /// handle that case. + /// FIXME: We should replace this with pointee_iterator> + /// when we can write that to filter out the null values. Then caller code + /// will become simpler. + MutableArrayRef assumptions() { + if (!Scanned) + scanFunction(); + return AssumeHandles; + } +}; + +/// \brief A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis { + static char PassID; + +public: + typedef AssumptionCache Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "AssumptionAnalysis"; } + + AssumptionAnalysis() {} + AssumptionAnalysis(const AssumptionAnalysis &Arg) {} + AssumptionAnalysis(AssumptionAnalysis &&Arg) {} + AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; } + AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; } + + AssumptionCache run(Function &F) { return AssumptionCache(F); } +}; + +/// \brief Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "AssumptionPrinterPass"; } +}; + +/// \brief An immutable pass that tracks lazily created \c AssumptionCache +/// objects. +/// +/// This is essentially a workaround for the legacy pass manager's weaknesses +/// which associates each assumption cache with Function and clears it if the +/// function is deleted. The nature of the AssumptionCache is that it is not +/// invalidated by any changes to the function body and so this is sufficient +/// to be conservatively correct. +class AssumptionCacheTracker : public ImmutablePass { + /// A callback value handle applied to function objects, which we use to + /// delete our cache of intrinsics for a function when it is deleted. + class FunctionCallbackVH : public CallbackVH { + AssumptionCacheTracker *ACT; + void deleted() override; + + public: + typedef DenseMapInfo DMI; + + FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr) + : CallbackVH(V), ACT(ACT) {} + }; + + friend FunctionCallbackVH; + + typedef DenseMap, + FunctionCallbackVH::DMI> FunctionCallsMap; + FunctionCallsMap AssumptionCaches; + +public: + /// \brief Get the cached assumptions for a function. + /// + /// If no assumptions are cached, this will scan the function. Otherwise, the + /// existing cache will be returned. + AssumptionCache &getAssumptionCache(Function &F); + + AssumptionCacheTracker(); + ~AssumptionCacheTracker(); + + void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } + + void verifyAnalysis() const override; + bool doFinalization(Module &) override { + verifyAnalysis(); + return false; + } + + static char ID; // Pass identification, replacement for typeid +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/AssumptionTracker.h b/include/llvm/Analysis/AssumptionTracker.h deleted file mode 100644 index 5a050a8..0000000 --- a/include/llvm/Analysis/AssumptionTracker.h +++ /dev/null @@ -1,128 +0,0 @@ -//===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a pass that keeps track of @llvm.assume intrinsics in -// the functions of a module (allowing assumptions within any function to be -// found cheaply by other parts of the optimizer). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H -#define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Pass.h" -#include - -namespace llvm { - -/// An immutable pass that tracks @llvm.assume intrinsics in a module. -class AssumptionTracker : public ImmutablePass { - /// A callback value handle applied to function objects, which we use to - /// delete our cache of intrinsics for a function when it is deleted. - class FunctionCallbackVH : public CallbackVH { - AssumptionTracker *AT; - void deleted() override; - - public: - typedef DenseMapInfo DMI; - - FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr) - : CallbackVH(V), AT(AT) {} - }; - - /// A callback value handle applied to call instructions, which keeps - /// track of the call's parent function so that we can remove a - /// assumption intrinsic call from our cache when the instruction is - /// deleted. - class CallCallbackVH : public CallbackVH { - AssumptionTracker *AT; - void deleted() override; - - // We store the function here because we need it to lookup the set - // containing this handle when the underlying CallInst is being deleted. - Function *F; - - public: - typedef DenseMapInfo DMI; - - CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr) - : CallbackVH(I), AT(AT), F(nullptr) { - if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey()) - F = I->getParent()->getParent(); - } - - operator CallInst*() const { - Value *V = getValPtr(); - if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey()) - return reinterpret_cast(V); - - return cast(V); - } - - CallInst *operator->() const { return cast(getValPtr()); } - CallInst &operator*() const { return *cast(getValPtr()); } - }; - - friend FunctionCallbackVH; - friend CallCallbackVH; - - // FIXME: SmallSet might be better here, but it currently has no iterators. - typedef DenseSet CallHandleSet; - typedef DenseMap, - FunctionCallbackVH::DMI> FunctionCallsMap; - FunctionCallsMap CachedAssumeCalls; - - /// Scan the provided function for @llvm.assume intrinsic calls. Returns an - /// iterator to the set for this function in the CachedAssumeCalls map. - FunctionCallsMap::iterator scanFunction(Function *F); - -public: - /// Remove the cache of @llvm.assume intrinsics for the given function. - void forgetCachedAssumptions(Function *F); - - /// Add an @llvm.assume intrinsic to the cache for its parent function. - void registerAssumption(CallInst *CI); - - typedef CallHandleSet::iterator assumption_iterator; - typedef iterator_range assumption_range; - - inline assumption_range assumptions(Function *F) { - FunctionCallsMap::iterator I = CachedAssumeCalls.find_as(F); - if (I == CachedAssumeCalls.end()) { - I = scanFunction(F); - } - - return assumption_range(I->second->begin(), I->second->end()); - } - - AssumptionTracker(); - ~AssumptionTracker(); - - void releaseMemory() override { - CachedAssumeCalls.shrink_and_clear(); - } - - void verifyAnalysis() const override; - bool doFinalization(Module &) override { - verifyAnalysis(); - return false; - } - - static char ID; // Pass identification, replacement for typeid -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4414c84..89eef68 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -111,6 +111,10 @@ public: void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors, uint32_t Weight); + static uint32_t getBranchWeightStackProtector(bool IsLikely) { + return IsLikely ? (1u << 20) - 1 : 1; + } + private: // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 1533b36..0d4fe93 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -21,135 +21,25 @@ #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H -#include "llvm/IR/PassManager.h" #include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/PassManager.h" namespace llvm { -class CGSCCAnalysisManager; - -class CGSCCPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCPassManager() {} - CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - /// \brief Run all of the CGSCC passes in this pass manager over a SCC. - PreservedAnalyses run(LazyCallGraph::SCC *C, - CGSCCAnalysisManager *AM = nullptr); - - template void addPass(CGSCCPassT Pass) { - Passes.emplace_back(new CGSCCPassModel(std::move(Pass))); - } - - static StringRef name() { return "CGSCCPassManager"; } - -private: - // Pull in the concept type and model template specialized for SCCs. - typedef detail::PassConcept - CGSCCPassConcept; - template - struct CGSCCPassModel - : detail::PassModel { - CGSCCPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; - - CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class CGSCCAnalysisManager : public detail::AnalysisManagerBase< - CGSCCAnalysisManager, LazyCallGraph::SCC *> { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // Most public APIs are inherited from the CRTP base class. - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManager() {} - CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} - CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); - return *this; - } - - /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; - - /// \brief Clear the function analysis result cache. - /// - /// This routine allows cleaning up when the set of functions itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); - -private: - CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - CGSCCAnalysisManager & - operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, - LazyCallGraph::SCC *C) const; - - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Invalidate the results for a function.. - void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); +/// \brief The CGSCC pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequency of SCC passes over each SCC that the manager is run over. This +/// typedef serves as a convenient way to refer to this construct. +typedef PassManager CGSCCPassManager; - /// \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>>> CGSCCAnalysisResultListT; - - /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - CGSCCAnalysisResultListMapT; - - /// \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. - CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; - - /// \brief Map type from a pair of analysis ID and function pointer to an - /// iterator into a particular result list. - typedef DenseMap, - CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; - - /// \brief Map from an analysis ID and function to a particular cached - /// analysis result. - CGSCCAnalysisResultMapT CGSCCAnalysisResults; -}; +/// \brief The CGSCC analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This typedef serves as a convenient way to refer to this +/// construct in the adaptors and proxies used to integrate this into the larger +/// pass manager infrastructure. +typedef AnalysisManager CGSCCAnalysisManager; /// \brief A module analysis which acts as a proxy for a CGSCC analysis /// manager. @@ -187,7 +77,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c CGSCCAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: CGSCCAnalysisManager *CGAM; @@ -195,12 +85,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; } + explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - CGSCCAnalysisManagerModuleProxy( - const CGSCCAnalysisManagerModuleProxy &Arg) + CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg) : CGAM(Arg.CGAM) {} CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) : CGAM(std::move(Arg.CGAM)) {} @@ -219,7 +110,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the CGSCC analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -257,7 +148,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(LazyCallGraph::SCC *) { return false; } + bool invalidate(LazyCallGraph::SCC &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -265,12 +156,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; } + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - ModuleAnalysisManagerCGSCCProxy( - const ModuleAnalysisManagerCGSCCProxy &Arg) + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg) : MAM(Arg.MAM) {} ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) : MAM(std::move(Arg.MAM)) {} @@ -283,7 +175,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(LazyCallGraph::SCC *) { return Result(*MAM); } + Result run(LazyCallGraph::SCC &) { return Result(*MAM); } private: static char PassID; @@ -323,7 +215,7 @@ public: } /// \brief Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { assert(AM && "We need analyses to compute the call graph!"); // Setup the CGSCC analysis manager from its proxy. @@ -335,15 +227,17 @@ public: PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { - PreservedAnalyses PassPA = Pass.run(&C, &CGAM); + PreservedAnalyses PassPA = Pass.run(C, &CGAM); // We know that the CGSCC pass couldn't have invalidated any other // SCC's analyses (that's the contract of a CGSCC pass), so - // directly handle the CGSCC analysis manager's invalidation here. + // directly handle the CGSCC analysis manager's invalidation here. We + // also update the preserved set of analyses to reflect that invalidated + // analyses are now safe to preserve. // FIXME: This isn't quite correct. We need to handle the case where the // pass updated the CG, particularly some child of the current SCC, and // invalidate its analyses. - CGAM.invalidate(&C, PassPA); + PassPA = CGAM.invalidate(C, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -409,7 +303,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); + bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -417,6 +311,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; } + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -441,7 +337,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(LazyCallGraph::SCC *C); + Result run(LazyCallGraph::SCC &C); private: static char PassID; @@ -479,7 +375,7 @@ public: const CGSCCAnalysisManager &getManager() const { return *CGAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const CGSCCAnalysisManager *CGAM; @@ -487,6 +383,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; } + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC @@ -505,7 +403,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c CGAM reference into the /// result. - Result run(Function *) { return Result(*CGAM); } + Result run(Function &) { return Result(*CGAM); } private: static char PassID; @@ -531,7 +429,8 @@ public: : Pass(Arg.Pass) {} CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { + friend void swap(CGSCCToFunctionPassAdaptor &LHS, + CGSCCToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -541,21 +440,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(C).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (LazyCallGraph::Node *N : *C) { - PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); + for (LazyCallGraph::Node *N : C) { + PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. + // Also, update the preserved analyses to reflect that once invalidated + // these can again be preserved. if (FAM) - FAM->invalidate(&N->getFunction(), PassPA); + PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -585,7 +486,6 @@ CGSCCToFunctionPassAdaptor createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(CGSCCToFunctionPassAdaptor(std::move(Pass))); } - } #endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 76d9073..64d288a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -273,8 +273,8 @@ private: /// CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences; - CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; - void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + CallGraphNode(const CallGraphNode &) = delete; + void operator=(const CallGraphNode &) = delete; void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 59502df..2f59691 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -20,7 +20,7 @@ #include "llvm/IR/CallSite.h" namespace llvm { -class AssumptionTracker; +class AssumptionCache; class BasicBlock; class Loop; class Function; @@ -93,13 +93,13 @@ struct CodeMetrics { /// \brief Collect a loop's ephemeral values (those used only by an assume /// or similar intrinsics in the loop). - static void collectEphemeralValues(const Loop *L, AssumptionTracker *AT, - SmallPtrSetImpl &EphValues); + static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); /// \brief Collect a functions's ephemeral values (those used only by an /// assume or similar intrinsics in the function). - static void collectEphemeralValues(const Function *L, AssumptionTracker *AT, - SmallPtrSetImpl &EphValues); + static void collectEphemeralValues(const Function *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); }; } diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 1041e3f..e01aa54 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -278,8 +278,8 @@ namespace llvm { /// DependenceAnalysis - This class is the main dependence-analysis driver. /// class DependenceAnalysis : public FunctionPass { - void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; - DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; + void operator=(const DependenceAnalysis &) = delete; + DependenceAnalysis(const DependenceAnalysis &) = delete; public: /// depends - Tests for a dependence between the Src and Dst instructions. /// Returns NULL if no dependence; otherwise, returns a Dependence (or a diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h deleted file mode 100644 index 574c947..0000000 --- a/include/llvm/Analysis/FindUsedTypes.h +++ /dev/null @@ -1,66 +0,0 @@ -//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass is used to seek out all of the types in use by the program. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H -#define LLVM_ANALYSIS_FINDUSEDTYPES_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/Pass.h" - -namespace llvm { - -class Type; -class Value; - -class FindUsedTypes : public ModulePass { - SetVector UsedTypes; -public: - static char ID; // Pass identification, replacement for typeid - FindUsedTypes() : ModulePass(ID) { - initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); - } - - /// getTypes - After the pass has been run, return the set containing all of - /// the types used in the module. - /// - const SetVector &getTypes() const { return UsedTypes; } - - /// Print the types found in the module. If the optional Module parameter is - /// passed in, then the types are printed symbolically if possible, using the - /// symbol table from the module. - /// - void print(raw_ostream &o, const Module *M) const override; - -private: - /// IncorporateType - Incorporate one type and all of its subtypes into the - /// collection of used types. - /// - void IncorporateType(Type *Ty); - - /// IncorporateValue - Incorporate all of the types used by this value. - /// - void IncorporateValue(const Value *V); - -public: - /// run - This incorporates all types used by the specified module - bool runOnModule(Module &M) override; - - /// getAnalysisUsage - We do not modify anything. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h deleted file mode 100644 index c1654cc..0000000 --- a/include/llvm/Analysis/FunctionTargetTransformInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass wraps a TargetTransformInfo in a FunctionPass so that it can -// forward along the current Function so that we can make target specific -// decisions based on the particular subtarget specified for each Function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H -#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H - -#include "llvm/Pass.h" -#include "TargetTransformInfo.h" - -namespace llvm { -class FunctionTargetTransformInfo final : public FunctionPass { -private: - const Function *Fn; - const TargetTransformInfo *TTI; - - FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) - LLVM_DELETED_FUNCTION; - void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; - -public: - static char ID; - FunctionTargetTransformInfo(); - - // Implementation boilerplate. - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnFunction(Function &F) override; - - // Shimmed functions from TargetTransformInfo. - void - getUnrollingPreferences(Loop *L, - TargetTransformInfo::UnrollingPreferences &UP) const { - TTI->getUnrollingPreferences(Fn, L, UP); - } -}; -} -#endif diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 81795ba..fdee9f8 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -19,11 +19,11 @@ #include namespace llvm { -class AssumptionTracker; +class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; -class TargetTransformInfo; +class TargetTransformInfoWrapperPass; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -77,7 +77,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Cost < Threshold; } @@ -100,8 +100,8 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { - const TargetTransformInfo *TTI; - AssumptionTracker *AT; + TargetTransformInfoWrapperPass *TTIWP; + AssumptionCacheTracker *ACT; public: static char ID; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 51f6e85..1ebf981 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -37,7 +37,7 @@ namespace llvm { template class ArrayRef; - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class Instruction; class DataLayout; @@ -52,7 +52,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySubInst - Given operands for a Sub, see if we can @@ -61,35 +61,34 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, - const Instruction *CxtI = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, - const Instruction *CxtI = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. - Value *SimplifyFMulInst(Value *LHS, Value *RHS, - FastMathFlags FMF, + Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyMulInst - Given operands for a Mul, see if we can @@ -97,7 +96,7 @@ namespace llvm { Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySDivInst - Given operands for an SDiv, see if we can @@ -106,7 +105,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyUDivInst - Given operands for a UDiv, see if we can @@ -115,16 +114,16 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFDivInst(Value *LHS, Value *RHS, + Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySRemInst - Given operands for an SRem, see if we can @@ -133,7 +132,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyURemInst - Given operands for a URem, see if we can @@ -142,16 +141,16 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFRemInst(Value *LHS, Value *RHS, + Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyShlInst - Given operands for a Shl, see if we can @@ -160,7 +159,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyLShrInst - Given operands for a LShr, see if we can @@ -169,7 +168,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyAShrInst - Given operands for a AShr, see if we can @@ -178,7 +177,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyAndInst - Given operands for an And, see if we can @@ -186,7 +185,7 @@ namespace llvm { Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyOrInst - Given operands for an Or, see if we can @@ -194,7 +193,7 @@ namespace llvm { Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyXorInst - Given operands for a Xor, see if we can @@ -202,7 +201,7 @@ namespace llvm { Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can @@ -211,7 +210,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, Instruction *CxtI = nullptr); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can @@ -220,7 +219,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold @@ -229,7 +228,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can @@ -237,7 +236,7 @@ namespace llvm { Value *SimplifyGEPInst(ArrayRef Ops, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we @@ -247,7 +246,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold @@ -255,7 +254,7 @@ namespace llvm { Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); //=== Helper functions for higher up the class hierarchy. @@ -267,7 +266,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can @@ -276,8 +275,19 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the + /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp. + Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const FastMathFlags &FMF, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. @@ -287,7 +297,7 @@ namespace llvm { User::op_iterator ArgEnd, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// \brief Given a function and set of arguments, see if we can fold the @@ -298,7 +308,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyInstruction - See if we can compute a simplified version of this @@ -306,8 +316,7 @@ namespace llvm { Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); - + AssumptionCache *AC = nullptr); /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses /// recursively. @@ -321,7 +330,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); + AssumptionCache *AC = nullptr); /// \brief Recursively attempt to simplify an instruction. /// @@ -333,7 +342,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); + AssumptionCache *AC = nullptr); } // end namespace llvm #endif diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 5b0176c..591e794 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -16,7 +16,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Pass.h" - #include namespace llvm { diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 9a59844..b0b9068 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -46,11 +46,11 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/Allocator.h" #include namespace llvm { -class ModuleAnalysisManager; class PreservedAnalyses; class raw_ostream; @@ -252,6 +252,12 @@ public: /// \brief Test if this SCC is a descendant of \a C. bool isDescendantOf(const SCC &C) const; + /// \brief Short name useful for debugging or logging. + /// + /// We use the name of the first function in the SCC to name the SCC for + /// the purposes of debugging and logging. + StringRef getName() const { return (*begin())->getFunction().getName(); } + ///@{ /// \name Mutation API /// @@ -537,11 +543,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "Lazy CallGraph Analysis"; } + /// \brief Compute the \c LazyCallGraph for the module \c M. /// /// This just builds the set of entry points to the call graph. The rest is /// built lazily as it is walked. - LazyCallGraph run(Module *M) { return LazyCallGraph(*M); } + LazyCallGraph run(Module &M) { return LazyCallGraph(M); } private: static char PassID; @@ -556,7 +564,7 @@ class LazyCallGraphPrinterPass { public: explicit LazyCallGraphPrinterPass(raw_ostream &OS); - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM); static StringRef name() { return "LazyCallGraphPrinterPass"; } }; diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 52cc0d1..51f6b0c 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -18,7 +18,7 @@ #include "llvm/Pass.h" namespace llvm { - class AssumptionTracker; + class AssumptionCache; class Constant; class DataLayout; class DominatorTree; @@ -26,16 +26,15 @@ namespace llvm { class TargetLibraryInfo; class Value; -/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint -/// information. +/// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { - AssumptionTracker *AT; + AssumptionCache *AC; const DataLayout *DL; class TargetLibraryInfo *TLI; DominatorTree *DT; void *PImpl; - LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; - void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; + LazyValueInfo(const LazyValueInfo&) = delete; + void operator=(const LazyValueInfo&) = delete; public: static char ID; LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { @@ -43,7 +42,7 @@ public: } ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } - /// Tristate - This is used to return true/false/dunno results. + /// This is used to return true/false/dunno results. enum Tristate { Unknown = -1, False = 0, True = 1 }; @@ -51,33 +50,33 @@ public: // Public query interface. - /// getPredicateOnEdge - Determine whether the specified value comparison - /// with a constant is known to be true or false on the specified CFG edge. + /// Determine whether the specified value comparison with a constant is known + /// to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - /// getPredicateAt - Determine whether the specified value comparison - /// with a constant is known to be true or false at the specified instruction + /// Determine whether the specified value comparison with a constant is known + /// to be true or false at the specified instruction /// (from an assume intrinsic). Pred is a CmpInst predicate. Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, Instruction *CxtI); - /// getConstant - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant at the end of the specified block. Return null if not. Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); - /// getConstantOnEdge - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant on the specified edge. Return null if not. Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - /// threadEdge - Inform the analysis cache that we have threaded an edge from + /// Inform the analysis cache that we have threaded an edge from /// PredBB to OldSucc to be from PredBB to NewSucc instead. void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); - /// eraseBlock - Inform the analysis cache that we have erased a block. + /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); // Implementation boilerplate. diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 8bd747f..e6427a4 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -18,6 +18,7 @@ #include "llvm/Analysis/AliasAnalysis.h" namespace llvm { +class InvokeInst; /// LibCallLocationInfo - This struct describes a set of memory locations that /// are accessed by libcalls. Identification of a location is doing with a @@ -162,6 +163,28 @@ namespace llvm { virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; }; + enum class EHPersonality { + Unknown, + GNU_Ada, + GNU_C, + GNU_CXX, + GNU_ObjC, + MSVC_X86SEH, + MSVC_Win64SEH, + MSVC_CXX, + }; + + /// \brief See if the given exception handling personality function is one + /// that we understand. If so, return a description of it; otherwise return + /// Unknown. + EHPersonality classifyEHPersonality(const Value *Pers); + + /// \brief Returns true if this personality function catches asynchronous + /// exceptions. + bool isAsynchronousEHPersonality(EHPersonality Pers); + + bool canSimplifyInvokeNoUnwind(const InvokeInst *II); + } // end namespace llvm #endif diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h new file mode 100644 index 0000000..323af98 --- /dev/null +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -0,0 +1,290 @@ +//===- llvm/Analysis/LoopAccessAnalysis.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 interface for the loop memory dependence framework that +// was originally developed for the Loop Vectorizer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H +#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class Value; +class DataLayout; +class AliasAnalysis; +class ScalarEvolution; +class Loop; +class SCEV; + +/// Optimization analysis message produced during vectorization. Messages inform +/// the user why vectorization did not occur. +class LoopAccessReport { + std::string Message; + const Instruction *Instr; + +protected: + LoopAccessReport(const Twine &Message, const Instruction *I) + : Message(Message.str()), Instr(I) {} + +public: + LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {} + + template LoopAccessReport &operator<<(const A &Value) { + raw_string_ostream Out(Message); + Out << Value; + return *this; + } + + const Instruction *getInstr() const { return Instr; } + + std::string &str() { return Message; } + const std::string &str() const { return Message; } + operator Twine() { return Message; } + + /// \brief Emit an analysis note for \p PassName with the debug location from + /// the instruction in \p Message if available. Otherwise use the location of + /// \p TheLoop. + static void emitAnalysis(const LoopAccessReport &Message, + const Function *TheFunction, + const Loop *TheLoop, + const char *PassName); +}; + +/// \brief Collection of parameters shared beetween the Loop Vectorizer and the +/// Loop Access Analysis. +struct VectorizerParams { + /// \brief Maximum SIMD width. + static const unsigned MaxVectorWidth; + + /// \brief VF as overridden by the user. + static unsigned VectorizationFactor; + /// \brief Interleave factor as overridden by the user. + static unsigned VectorizationInterleave; + /// \brief True if force-vector-interleave was specified by the user. + static bool isInterleaveForced(); + + /// \\brief When performing memory disambiguation checks at runtime do not + /// make more than this number of comparisons. + static unsigned RuntimeMemoryCheckThreshold; +}; + +/// \brief Drive the analysis of memory accesses in the loop +/// +/// This class is responsible for analyzing the memory accesses of a loop. It +/// collects the accesses and then its main helper the AccessAnalysis class +/// finds and categorizes the dependences in buildDependenceSets. +/// +/// For memory dependences that can be analyzed at compile time, it determines +/// whether the dependence is part of cycle inhibiting vectorization. This work +/// is delegated to the MemoryDepChecker class. +/// +/// For memory dependences that cannot be determined at compile time, it +/// generates run-time checks to prove independence. This is done by +/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the +/// RuntimePointerCheck class. +class LoopAccessInfo { +public: + /// This struct holds information about the memory runtime legality check that + /// a group of pointers do not overlap. + struct RuntimePointerCheck { + RuntimePointerCheck() : Need(false) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + Starts.clear(); + Ends.clear(); + IsWritePtr.clear(); + DependencySetId.clear(); + AliasSetId.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, + unsigned DepSetId, unsigned ASId, + const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + bool needsChecking(unsigned I, unsigned J) const; + + /// \brief Print the list run-time memory checks necessary. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + /// Holds the pointers that we need to check. + SmallVector, 2> Pointers; + /// Holds the pointer value at the beginning of the loop. + SmallVector Starts; + /// Holds the pointer value at the end of the loop. + SmallVector Ends; + /// Holds the information if this pointer is used for writing to memory. + SmallVector IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + SmallVector DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + SmallVector AliasSetId; + }; + + LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout *DL, + const TargetLibraryInfo *TLI, AliasAnalysis *AA, + DominatorTree *DT, const ValueToValueMap &Strides); + + /// Return true we can analyze the memory accesses in the loop and there are + /// no memory dependence cycles. + bool canVectorizeMemory() const { return CanVecMem; } + + const RuntimePointerCheck *getRuntimePointerCheck() const { + return &PtrRtCheck; + } + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, + DominatorTree *DT); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V) const; + + unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } + unsigned getNumStores() const { return NumStores; } + unsigned getNumLoads() const { return NumLoads;} + + /// \brief Add code that checks at runtime if the accessed arrays overlap. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + std::pair + addRuntimeCheck(Instruction *Loc) const; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + const Optional &getReport() const { return Report; } + + /// \brief Print the information about the memory accesses in the loop. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// \brief Used to ensure that if the analysis was run with speculating the + /// value of symbolic strides, the client queries it with the same assumption. + /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI. + unsigned NumSymbolicStrides; + +private: + /// \brief Analyze the loop. Substitute symbolic strides using Strides. + void analyzeLoop(const ValueToValueMap &Strides); + + /// \brief Check if the structure of the loop allows it to be analyzed by this + /// pass. + bool canAnalyzeLoop(); + + void emitAnalysis(LoopAccessReport &Message); + + /// We need to check that all of the pointers in this list are disjoint + /// at runtime. + RuntimePointerCheck PtrRtCheck; + Loop *TheLoop; + ScalarEvolution *SE; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + + unsigned NumLoads; + unsigned NumStores; + + unsigned MaxSafeDepDistBytes; + + /// \brief Cache the result of analyzeLoop. + bool CanVecMem; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + Optional Report; +}; + +Value *stripIntegerCast(Value *V); + +///\brief Return the SCEV corresponding to a pointer with the symbolic stride +///replaced with constant one. +/// +/// If \p OrigPtr is not null, use it to look up the stride value instead of \p +/// Ptr. \p PtrToStride provides the mapping between the pointer value and its +/// stride as collected by LoopVectorizationLegality::collectStridedAccess. +const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE, + const ValueToValueMap &PtrToStride, + Value *Ptr, Value *OrigPtr = nullptr); + +/// \brief This analysis provides dependence information for the memory accesses +/// of a loop. +/// +/// It runs the analysis for a loop on demand. This can be initiated by +/// querying the loop access info via LAA::getInfo. getInfo return a +/// LoopAccessInfo object. See this class for the specifics of what information +/// is provided. +class LoopAccessAnalysis : public FunctionPass { +public: + static char ID; + + LoopAccessAnalysis() : FunctionPass(ID) { + initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// \brief Query the result of the loop access information for the loop \p L. + /// + /// If the client speculates (and then issues run-time checks) for the values + /// of symbolic strides, \p Strides provides the mapping (see + /// replaceSymbolicStrideSCEV). If there is no cached result available run + /// the analysis. + const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + + void releaseMemory() override { + // Invalidate the cache when the pass is freed. + LoopAccessInfoMap.clear(); + } + + /// \brief Print the result of the analysis when invoked with -analyze. + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + /// \brief The cache. + DenseMap> LoopAccessInfoMap; + + // The used analysis passes. + ScalarEvolution *SE; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index bef03e9..85c2da7 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -42,6 +42,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + template inline void RemoveFromVector(std::vector &V, T *N) { typename std::vector::iterator I = std::find(V.begin(), V.end(), N); @@ -74,9 +79,9 @@ class LoopBase { SmallPtrSet DenseBlockSet; - LoopBase(const LoopBase &) LLVM_DELETED_FUNCTION; + LoopBase(const LoopBase &) = delete; const LoopBase& - operator=(const LoopBase &) LLVM_DELETED_FUNCTION; + operator=(const LoopBase &) = delete; public: /// Loop ctor - This creates an empty loop. LoopBase() : ParentLoop(nullptr) {} @@ -496,18 +501,33 @@ class LoopInfoBase { friend class LoopBase; friend class LoopInfo; - void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION; - LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfoBase &) = delete; + LoopInfoBase(const LoopInfoBase &) = delete; public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } + LoopInfoBase(LoopInfoBase &&Arg) + : BBMap(std::move(Arg.BBMap)), + TopLevelLoops(std::move(Arg.TopLevelLoops)) { + // We have to clear the arguments top level loops as we've taken ownership. + Arg.TopLevelLoops.clear(); + } + LoopInfoBase &operator=(LoopInfoBase &&RHS) { + BBMap = std::move(RHS.BBMap); + + for (auto *L : TopLevelLoops) + delete L; + TopLevelLoops = std::move(RHS.TopLevelLoops); + RHS.TopLevelLoops.clear(); + return *this; + } + void releaseMemory() { - for (typename std::vector::iterator I = - TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) - delete *I; // Delete all of the loops... + BBMap.clear(); - BBMap.clear(); // Reset internal state of analysis + for (auto *L : TopLevelLoops) + delete L; TopLevelLoops.clear(); } @@ -576,8 +596,7 @@ public: /// list with the indicated loop. void changeTopLevelLoop(LoopT *OldLoop, LoopT *NewLoop) { - typename std::vector::iterator I = - std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); assert(I != TopLevelLoops.end() && "Old loop not at top level!"); *I = NewLoop; assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && @@ -595,7 +614,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename DenseMap::iterator I = BBMap.find(BB); + auto I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -617,8 +636,9 @@ public: void Analyze(DominatorTreeBase &DomTree); // Debugging - void print(raw_ostream &OS) const; + + void verify() const; }; // Implementation in LoopInfoImpl.h @@ -626,99 +646,23 @@ public: __extension__ extern template class LoopInfoBase; #endif -class LoopInfo : public FunctionPass { - LoopInfoBase LI; +class LoopInfo : public LoopInfoBase { + typedef LoopInfoBase BaseT; + friend class LoopBase; - void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION; - LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfo &) = delete; + LoopInfo(const LoopInfo &) = delete; public: - static char ID; // Pass identification, replacement for typeid - - LoopInfo() : FunctionPass(ID) { - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - } - - LoopInfoBase& getBase() { return LI; } + LoopInfo() {} - /// iterator/begin/end - The interface to the top-level loops in the current - /// function. - /// - typedef LoopInfoBase::iterator iterator; - typedef LoopInfoBase::reverse_iterator reverse_iterator; - inline iterator begin() const { return LI.begin(); } - inline iterator end() const { return LI.end(); } - inline reverse_iterator rbegin() const { return LI.rbegin(); } - inline reverse_iterator rend() const { return LI.rend(); } - bool empty() const { return LI.empty(); } - - /// getLoopFor - Return the inner most loop that BB lives in. If a basic - /// block is in no loop (for example the entry node), null is returned. - /// - inline Loop *getLoopFor(const BasicBlock *BB) const { - return LI.getLoopFor(BB); + LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast(Arg))) {} + LoopInfo &operator=(LoopInfo &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; } - /// operator[] - same as getLoopFor... - /// - inline const Loop *operator[](const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// getLoopDepth - Return the loop nesting level of the specified block. A - /// depth of 0 means the block is not inside any loop. - /// - inline unsigned getLoopDepth(const BasicBlock *BB) const { - return LI.getLoopDepth(BB); - } - - // isLoopHeader - True if the block is a loop header node - inline bool isLoopHeader(BasicBlock *BB) const { - return LI.isLoopHeader(BB); - } - - /// runOnFunction - Calculate the natural loop information. - /// - bool runOnFunction(Function &F) override; - - void verifyAnalysis() const override; - - void releaseMemory() override { LI.releaseMemory(); } - - void print(raw_ostream &O, const Module* M = nullptr) const override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// removeLoop - This removes the specified top-level loop from this loop info - /// object. The loop is not deleted, as it will presumably be inserted into - /// another loop. - inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } - - /// changeLoopFor - Change the top-level loop that contains BB to the - /// specified loop. This should be used by transformations that restructure - /// the loop hierarchy tree. - inline void changeLoopFor(BasicBlock *BB, Loop *L) { - LI.changeLoopFor(BB, L); - } - - /// changeTopLevelLoop - Replace the specified loop in the top-level loops - /// list with the indicated loop. - inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { - LI.changeTopLevelLoop(OldLoop, NewLoop); - } - - /// addTopLevelLoop - This adds the specified loop to the collection of - /// top-level loops. - inline void addTopLevelLoop(Loop *New) { - LI.addTopLevelLoop(New); - } - - /// removeBlock - This method completely removes BB from all data structures, - /// including all of the Loop objects it is nested in and our mapping from - /// BasicBlocks to loops. - void removeBlock(BasicBlock *BB) { - LI.removeBlock(BB); - } + // Most of the public interface is provided via LoopInfoBase. /// updateUnloop - Update LoopInfo after removing the last backedge from a /// loop--now the "unloop". This updates the loop forest and parent loops for @@ -748,7 +692,6 @@ public: } }; - // Allow clients to walk the list of nested loops... template <> struct GraphTraits { typedef const Loop NodeType; @@ -776,6 +719,65 @@ template <> struct GraphTraits { } }; +/// \brief Analysis pass that exposes the \c LoopInfo for a function. +class LoopAnalysis { + static char PassID; + +public: + typedef LoopInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "LoopAnalysis"; } + + LoopAnalysis() {} + LoopAnalysis(const LoopAnalysis &Arg) {} + LoopAnalysis(LoopAnalysis &&Arg) {} + LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; } + LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; } + + LoopInfo run(Function &F, AnalysisManager *AM); +}; + +/// \brief Printer pass for the \c LoopAnalysis results. +class LoopPrinterPass { + raw_ostream &OS; + +public: + explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "LoopPrinterPass"; } +}; + +/// \brief The legacy pass manager's analysis pass to compute loop information. +class LoopInfoWrapperPass : public FunctionPass { + LoopInfo LI; + +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfoWrapperPass() : FunctionPass(ID) { + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + LoopInfo &getLoopInfo() { return LI; } + const LoopInfo &getLoopInfo() const { return LI; } + + /// \brief Calculate the natural loop information for a given function. + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void releaseMemory() override { LI.releaseMemory(); } + + void print(raw_ostream &O, const Module *M = nullptr) const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 948be0f..3321f39 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -545,6 +545,25 @@ void LoopInfoBase::print(raw_ostream &OS) const { #endif } +template +void LoopInfoBase::verify() const { + DenseSet Loops; + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(&Loops); + } + + // Verify that blocks are mapped to valid loops. +#ifndef NDEBUG + for (auto &Entry : BBMap) { + BlockT *BB = Entry.first; + LoopT *L = Entry.second; + assert(Loops.count(L) && "orphaned loop"); + assert(L->contains(BB) && "orphaned block"); + } +#endif +} + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 4d315d1..77610b3 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -28,7 +28,7 @@ namespace llvm { class Instruction; class CallSite; class AliasAnalysis; - class AssumptionTracker; + class AssumptionCache; class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; @@ -326,7 +326,7 @@ namespace llvm { AliasAnalysis *AA; const DataLayout *DL; DominatorTree *DT; - AssumptionTracker *AT; + AssumptionCache *AC; std::unique_ptr PredCache; public: @@ -366,12 +366,16 @@ namespace llvm { /// getNonLocalPointerDependency - Perform a full dependency query for an - /// access to the specified (non-volatile) memory location, returning the - /// set of instructions that either define or clobber the value. + /// access to the QueryInst's specified memory location, returning the set + /// of instructions that either define or clobber the value. /// - /// This method assumes the pointer has a "NonLocal" dependency within BB. - void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, + /// Warning: For a volatile query instruction, the dependencies will be + /// accurate, and thus usable for reordering, but it is never legal to + /// remove the query instruction. + /// + /// This method assumes the pointer has a "NonLocal" dependency within + /// QueryInst's parent basic block. + void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl &Result); /// removeInstruction - Remove an instruction from the dependence analysis, @@ -424,13 +428,15 @@ namespace llvm { MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); - bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + bool getNonLocalPointerDepFromBB(Instruction *QueryInst, + const PHITransAddr &Pointer, const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, SmallVectorImpl &Result, DenseMap &Visited, bool SkipFirstBlock = false); - MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst, + const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 0790e97..38730d8 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -18,7 +18,7 @@ #include "llvm/IR/Instruction.h" namespace llvm { - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class DataLayout; class TargetLibraryInfo; @@ -44,13 +44,13 @@ class PHITransAddr { const TargetLibraryInfo *TLI; /// A cache of @llvm.assume calls used by SimplifyInstruction. - AssumptionTracker *AT; - + AssumptionCache *AC; + /// InstInputs - The inputs for our symbolic address. SmallVector InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL, AssumptionTracker *AT) - : Addr(addr), DL(DL), TLI(nullptr), AT(AT) { + PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 10a5605..530faa7 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -162,6 +162,14 @@ namespace llvm { // createJumpInstrTableInfoPass - This creates a pass that stores information // about the jump tables created by JumpInstrTables ImmutablePass *createJumpInstrTableInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + } #endif diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 6ff7f97..1c7f4d3 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -115,8 +115,8 @@ public: typedef typename Tr::RegionT RegionT; private: - RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION; - const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; + RegionNodeBase(const RegionNodeBase &) = delete; + const RegionNodeBase &operator=(const RegionNodeBase &) = delete; /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this @@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase { typedef typename InvBlockTraits::ChildIteratorType PredIterTy; friend class RegionInfoBase; - RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION; - const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; + RegionBase(const RegionBase &) = delete; + const RegionBase &operator=(const RegionBase &) = delete; // Information necessary to manage this Region. RegionInfoT *RI; @@ -674,8 +674,8 @@ class RegionInfoBase { RegionInfoBase(); virtual ~RegionInfoBase(); - RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; - const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) = delete; + const RegionInfoBase &operator=(const RegionInfoBase &) = delete; DomTreeT *DT; PostDomTreeT *PDT; diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index b5d0bb3..b0dc263 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -12,11 +12,11 @@ #ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H #define LLVM_ANALYSIS_REGIONINFOIMPL_H -#include "llvm/Analysis/RegionInfo.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 893402e..c60cea9 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -35,7 +35,7 @@ namespace llvm { class APInt; - class AssumptionTracker; + class AssumptionCache; class Constant; class ConstantInt; class DominatorTree; @@ -71,8 +71,8 @@ namespace llvm { unsigned short SubclassData; private: - SCEV(const SCEV &) LLVM_DELETED_FUNCTION; - void operator=(const SCEV &) LLVM_DELETED_FUNCTION; + SCEV(const SCEV &) = delete; + void operator=(const SCEV &) = delete; public: /// NoWrapFlags are bitfield indices into SubclassData. @@ -82,12 +82,13 @@ namespace llvm { /// operator. NSW is a misnomer that we use to mean no signed overflow or /// underflow. /// - /// AddRec expression may have a no-self-wraparound property if the - /// result can never reach the start value. This property is independent of - /// the actual start value and step direction. Self-wraparound is defined - /// purely in terms of the recurrence's loop, step size, and - /// bitwidth. Formally, a recurrence with no self-wraparound satisfies: - /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth). + /// AddRec expressions may have a no-self-wraparound property if, in + /// the integer domain, abs(step) * max-iteration(loop) <= + /// unsigned-max(bitwidth). This means that the recurrence will never reach + /// its start value if the step is non-zero. Computing the same value on + /// each iteration is not considered wrapping, and recurrences with step = 0 + /// are trivially . is independent of the sign of step and the + /// value the add recurrence starts with. /// /// Note that NUW and NSW are also valid properties of a recurrence, and /// either implies NW. For convenience, NW will be set for a recurrence @@ -225,7 +226,7 @@ namespace llvm { Function *F; /// The tracker for @llvm.assume intrinsics in this function. - AssumptionTracker *AT; + AssumptionCache *AC; /// LI - The loop information for the function we are currently analyzing. /// @@ -372,14 +373,17 @@ namespace llvm { /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap, 2> > LoopDispositions; + SmallVector, 2>> + LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. - DenseMap, 2> > BlockDispositions; + DenseMap< + const SCEV *, + SmallVector, 2>> + BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 94e665f..ff82db1 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 65ff2f6..9ccae5f 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -131,8 +131,8 @@ class SparseSolver { typedef std::pair Edge; std::set KnownFeasibleEdges; - SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION; - void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION; + SparseSolver(const SparseSolver&) = delete; + void operator=(const SparseSolver&) = delete; public: explicit SparseSolver(AbstractLatticeFunction *Lattice) : LatticeFunc(Lattice) {} diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h new file mode 100644 index 0000000..5c6f364 --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -0,0 +1,935 @@ +//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H +#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +// BEGIN ANDROID-SPECIFIC +#ifdef WIN32 +#ifdef fseeko +#undef fseeko +#endif +#ifdef ftello +#undef ftello +#endif +#endif // WIN32 +// END ANDROID-SPECIFIC + +namespace llvm { +class PreservedAnalyses; + + namespace LibFunc { + enum Func { + /// int _IO_getc(_IO_FILE * __fp); + under_IO_getc, + /// int _IO_putc(int __c, _IO_FILE * __fp); + under_IO_putc, + /// void operator delete[](void*); + ZdaPv, + /// void operator delete[](void*, nothrow); + ZdaPvRKSt9nothrow_t, + /// void operator delete[](void*, unsigned int); + ZdaPvj, + /// void operator delete[](void*, unsigned long); + ZdaPvm, + /// void operator delete(void*); + ZdlPv, + /// void operator delete(void*, nothrow); + ZdlPvRKSt9nothrow_t, + /// void operator delete(void*, unsigned int); + ZdlPvj, + /// void operator delete(void*, unsigned long); + ZdlPvm, + /// void *new[](unsigned int); + Znaj, + /// void *new[](unsigned int, nothrow); + ZnajRKSt9nothrow_t, + /// void *new[](unsigned long); + Znam, + /// void *new[](unsigned long, nothrow); + ZnamRKSt9nothrow_t, + /// void *new(unsigned int); + Znwj, + /// void *new(unsigned int, nothrow); + ZnwjRKSt9nothrow_t, + /// void *new(unsigned long); + Znwm, + /// void *new(unsigned long, nothrow); + ZnwmRKSt9nothrow_t, + /// double __cospi(double x); + cospi, + /// float __cospif(float x); + cospif, + /// int __cxa_atexit(void (*f)(void *), void *p, void *d); + cxa_atexit, + /// void __cxa_guard_abort(guard_t *guard); + /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. + cxa_guard_abort, + /// int __cxa_guard_acquire(guard_t *guard); + cxa_guard_acquire, + /// void __cxa_guard_release(guard_t *guard); + cxa_guard_release, + /// int __isoc99_scanf (const char *format, ...) + dunder_isoc99_scanf, + /// int __isoc99_sscanf(const char *s, const char *format, ...) + dunder_isoc99_sscanf, + /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); + memcpy_chk, + /// void *__memmove_chk(void *s1, const void *s2, size_t n, + /// size_t s1size); + memmove_chk, + /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); + memset_chk, + /// double __sincospi_stret(double x); + sincospi_stret, + /// float __sincospif_stret(float x); + sincospif_stret, + /// double __sinpi(double x); + sinpi, + /// float __sinpif(float x); + sinpif, + /// double __sqrt_finite(double x); + sqrt_finite, + /// float __sqrt_finite(float x); + sqrtf_finite, + /// long double __sqrt_finite(long double x); + sqrtl_finite, + /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); + stpcpy_chk, + /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + stpncpy_chk, + /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); + strcpy_chk, + /// char * __strdup(const char *s); + dunder_strdup, + /// char *__strncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + strncpy_chk, + /// char *__strndup(const char *s, size_t n); + dunder_strndup, + /// char * __strtok_r(char *s, const char *delim, char **save_ptr); + dunder_strtok_r, + /// int abs(int j); + abs, + /// int access(const char *path, int amode); + access, + /// double acos(double x); + acos, + /// float acosf(float x); + acosf, + /// double acosh(double x); + acosh, + /// float acoshf(float x); + acoshf, + /// long double acoshl(long double x); + acoshl, + /// long double acosl(long double x); + acosl, + /// double asin(double x); + asin, + /// float asinf(float x); + asinf, + /// double asinh(double x); + asinh, + /// float asinhf(float x); + asinhf, + /// long double asinhl(long double x); + asinhl, + /// long double asinl(long double x); + asinl, + /// double atan(double x); + atan, + /// double atan2(double y, double x); + atan2, + /// float atan2f(float y, float x); + atan2f, + /// long double atan2l(long double y, long double x); + atan2l, + /// float atanf(float x); + atanf, + /// double atanh(double x); + atanh, + /// float atanhf(float x); + atanhf, + /// long double atanhl(long double x); + atanhl, + /// long double atanl(long double x); + atanl, + /// double atof(const char *str); + atof, + /// int atoi(const char *str); + atoi, + /// long atol(const char *str); + atol, + /// long long atoll(const char *nptr); + atoll, + /// int bcmp(const void *s1, const void *s2, size_t n); + bcmp, + /// void bcopy(const void *s1, void *s2, size_t n); + bcopy, + /// void bzero(void *s, size_t n); + bzero, + /// void *calloc(size_t count, size_t size); + calloc, + /// double cbrt(double x); + cbrt, + /// float cbrtf(float x); + cbrtf, + /// long double cbrtl(long double x); + cbrtl, + /// double ceil(double x); + ceil, + /// float ceilf(float x); + ceilf, + /// long double ceill(long double x); + ceill, + /// int chmod(const char *path, mode_t mode); + chmod, + /// int chown(const char *path, uid_t owner, gid_t group); + chown, + /// void clearerr(FILE *stream); + clearerr, + /// int closedir(DIR *dirp); + closedir, + /// double copysign(double x, double y); + copysign, + /// float copysignf(float x, float y); + copysignf, + /// long double copysignl(long double x, long double y); + copysignl, + /// double cos(double x); + cos, + /// float cosf(float x); + cosf, + /// double cosh(double x); + cosh, + /// float coshf(float x); + coshf, + /// long double coshl(long double x); + coshl, + /// long double cosl(long double x); + cosl, + /// char *ctermid(char *s); + ctermid, + /// double exp(double x); + exp, + /// double exp10(double x); + exp10, + /// float exp10f(float x); + exp10f, + /// long double exp10l(long double x); + exp10l, + /// double exp2(double x); + exp2, + /// float exp2f(float x); + exp2f, + /// long double exp2l(long double x); + exp2l, + /// float expf(float x); + expf, + /// long double expl(long double x); + expl, + /// double expm1(double x); + expm1, + /// float expm1f(float x); + expm1f, + /// long double expm1l(long double x); + expm1l, + /// double fabs(double x); + fabs, + /// float fabsf(float x); + fabsf, + /// long double fabsl(long double x); + fabsl, + /// int fclose(FILE *stream); + fclose, + /// FILE *fdopen(int fildes, const char *mode); + fdopen, + /// int feof(FILE *stream); + feof, + /// int ferror(FILE *stream); + ferror, + /// int fflush(FILE *stream); + fflush, + /// int ffs(int i); + ffs, + /// int ffsl(long int i); + ffsl, + /// int ffsll(long long int i); + ffsll, + /// int fgetc(FILE *stream); + fgetc, + /// int fgetpos(FILE *stream, fpos_t *pos); + fgetpos, + /// char *fgets(char *s, int n, FILE *stream); + fgets, + /// int fileno(FILE *stream); + fileno, + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, + /// void flockfile(FILE *file); + flockfile, + /// double floor(double x); + floor, + /// float floorf(float x); + floorf, + /// long double floorl(long double x); + floorl, + /// double fmax(double x, double y); + fmax, + /// float fmaxf(float x, float y); + fmaxf, + /// long double fmaxl(long double x, long double y); + fmaxl, + /// double fmin(double x, double y); + fmin, + /// float fminf(float x, float y); + fminf, + /// long double fminl(long double x, long double y); + fminl, + /// double fmod(double x, double y); + fmod, + /// float fmodf(float x, float y); + fmodf, + /// long double fmodl(long double x, long double y); + fmodl, + /// FILE *fopen(const char *filename, const char *mode); + fopen, + /// FILE *fopen64(const char *filename, const char *opentype) + fopen64, + /// int fprintf(FILE *stream, const char *format, ...); + fprintf, + /// int fputc(int c, FILE *stream); + fputc, + /// int fputs(const char *s, FILE *stream); + fputs, + /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); + fread, + /// void free(void *ptr); + free, + /// double frexp(double num, int *exp); + frexp, + /// float frexpf(float num, int *exp); + frexpf, + /// long double frexpl(long double num, int *exp); + frexpl, + /// int fscanf(FILE *stream, const char *format, ... ); + fscanf, + /// int fseek(FILE *stream, long offset, int whence); + fseek, + /// int fseeko(FILE *stream, off_t offset, int whence); + fseeko, + /// int fseeko64(FILE *stream, off64_t offset, int whence) + fseeko64, + /// int fsetpos(FILE *stream, const fpos_t *pos); + fsetpos, + /// int fstat(int fildes, struct stat *buf); + fstat, + /// int fstat64(int filedes, struct stat64 *buf) + fstat64, + /// int fstatvfs(int fildes, struct statvfs *buf); + fstatvfs, + /// int fstatvfs64(int fildes, struct statvfs64 *buf); + fstatvfs64, + /// long ftell(FILE *stream); + ftell, + /// off_t ftello(FILE *stream); + ftello, + /// off64_t ftello64(FILE *stream) + ftello64, + /// int ftrylockfile(FILE *file); + ftrylockfile, + /// void funlockfile(FILE *file); + funlockfile, + /// size_t fwrite(const void *ptr, size_t size, size_t nitems, + /// FILE *stream); + fwrite, + /// int getc(FILE *stream); + getc, + /// int getc_unlocked(FILE *stream); + getc_unlocked, + /// int getchar(void); + getchar, + /// char *getenv(const char *name); + getenv, + /// int getitimer(int which, struct itimerval *value); + getitimer, + /// int getlogin_r(char *name, size_t namesize); + getlogin_r, + /// struct passwd *getpwnam(const char *name); + getpwnam, + /// char *gets(char *s); + gets, + /// int gettimeofday(struct timeval *tp, void *tzp); + gettimeofday, + /// uint32_t htonl(uint32_t hostlong); + htonl, + /// uint16_t htons(uint16_t hostshort); + htons, + /// int iprintf(const char *format, ...); + iprintf, + /// int isascii(int c); + isascii, + /// int isdigit(int c); + isdigit, + /// long int labs(long int j); + labs, + /// int lchown(const char *path, uid_t owner, gid_t group); + lchown, + /// double ldexp(double x, int n); + ldexp, + /// float ldexpf(float x, int n); + ldexpf, + /// long double ldexpl(long double x, int n); + ldexpl, + /// long long int llabs(long long int j); + llabs, + /// double log(double x); + log, + /// double log10(double x); + log10, + /// float log10f(float x); + log10f, + /// long double log10l(long double x); + log10l, + /// double log1p(double x); + log1p, + /// float log1pf(float x); + log1pf, + /// long double log1pl(long double x); + log1pl, + /// double log2(double x); + log2, + /// float log2f(float x); + log2f, + /// double long double log2l(long double x); + log2l, + /// double logb(double x); + logb, + /// float logbf(float x); + logbf, + /// long double logbl(long double x); + logbl, + /// float logf(float x); + logf, + /// long double logl(long double x); + logl, + /// int lstat(const char *path, struct stat *buf); + lstat, + /// int lstat64(const char *path, struct stat64 *buf); + lstat64, + /// void *malloc(size_t size); + malloc, + /// void *memalign(size_t boundary, size_t size); + memalign, + /// void *memccpy(void *s1, const void *s2, int c, size_t n); + memccpy, + /// void *memchr(const void *s, int c, size_t n); + memchr, + /// int memcmp(const void *s1, const void *s2, size_t n); + memcmp, + /// void *memcpy(void *s1, const void *s2, size_t n); + memcpy, + /// void *memmove(void *s1, const void *s2, size_t n); + memmove, + // void *memrchr(const void *s, int c, size_t n); + memrchr, + /// void *memset(void *b, int c, size_t len); + memset, + /// void memset_pattern16(void *b, const void *pattern16, size_t len); + memset_pattern16, + /// int mkdir(const char *path, mode_t mode); + mkdir, + /// time_t mktime(struct tm *timeptr); + mktime, + /// double modf(double x, double *iptr); + modf, + /// float modff(float, float *iptr); + modff, + /// long double modfl(long double value, long double *iptr); + modfl, + /// double nearbyint(double x); + nearbyint, + /// float nearbyintf(float x); + nearbyintf, + /// long double nearbyintl(long double x); + nearbyintl, + /// uint32_t ntohl(uint32_t netlong); + ntohl, + /// uint16_t ntohs(uint16_t netshort); + ntohs, + /// int open(const char *path, int oflag, ... ); + open, + /// int open64(const char *filename, int flags[, mode_t mode]) + open64, + /// DIR *opendir(const char *dirname); + opendir, + /// int pclose(FILE *stream); + pclose, + /// void perror(const char *s); + perror, + /// FILE *popen(const char *command, const char *mode); + popen, + /// int posix_memalign(void **memptr, size_t alignment, size_t size); + posix_memalign, + /// double pow(double x, double y); + pow, + /// float powf(float x, float y); + powf, + /// long double powl(long double x, long double y); + powl, + /// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + pread, + /// int printf(const char *format, ...); + printf, + /// int putc(int c, FILE *stream); + putc, + /// int putchar(int c); + putchar, + /// int puts(const char *s); + puts, + /// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, + /// off_t offset); + pwrite, + /// void qsort(void *base, size_t nel, size_t width, + /// int (*compar)(const void *, const void *)); + qsort, + /// ssize_t read(int fildes, void *buf, size_t nbyte); + read, + /// ssize_t readlink(const char *path, char *buf, size_t bufsize); + readlink, + /// void *realloc(void *ptr, size_t size); + realloc, + /// void *reallocf(void *ptr, size_t size); + reallocf, + /// char *realpath(const char *file_name, char *resolved_name); + realpath, + /// int remove(const char *path); + remove, + /// int rename(const char *old, const char *new); + rename, + /// void rewind(FILE *stream); + rewind, + /// double rint(double x); + rint, + /// float rintf(float x); + rintf, + /// long double rintl(long double x); + rintl, + /// int rmdir(const char *path); + rmdir, + /// double round(double x); + round, + /// float roundf(float x); + roundf, + /// long double roundl(long double x); + roundl, + /// int scanf(const char *restrict format, ... ); + scanf, + /// void setbuf(FILE *stream, char *buf); + setbuf, + /// int setitimer(int which, const struct itimerval *value, + /// struct itimerval *ovalue); + setitimer, + /// int setvbuf(FILE *stream, char *buf, int type, size_t size); + setvbuf, + /// double sin(double x); + sin, + /// float sinf(float x); + sinf, + /// double sinh(double x); + sinh, + /// float sinhf(float x); + sinhf, + /// long double sinhl(long double x); + sinhl, + /// long double sinl(long double x); + sinl, + /// int siprintf(char *str, const char *format, ...); + siprintf, + /// int snprintf(char *s, size_t n, const char *format, ...); + snprintf, + /// int sprintf(char *str, const char *format, ...); + sprintf, + /// double sqrt(double x); + sqrt, + /// float sqrtf(float x); + sqrtf, + /// long double sqrtl(long double x); + sqrtl, + /// int sscanf(const char *s, const char *format, ... ); + sscanf, + /// int stat(const char *path, struct stat *buf); + stat, + /// int stat64(const char *path, struct stat64 *buf); + stat64, + /// int statvfs(const char *path, struct statvfs *buf); + statvfs, + /// int statvfs64(const char *path, struct statvfs64 *buf) + statvfs64, + /// char *stpcpy(char *s1, const char *s2); + stpcpy, + /// char *stpncpy(char *s1, const char *s2, size_t n); + stpncpy, + /// int strcasecmp(const char *s1, const char *s2); + strcasecmp, + /// char *strcat(char *s1, const char *s2); + strcat, + /// char *strchr(const char *s, int c); + strchr, + /// int strcmp(const char *s1, const char *s2); + strcmp, + /// int strcoll(const char *s1, const char *s2); + strcoll, + /// char *strcpy(char *s1, const char *s2); + strcpy, + /// size_t strcspn(const char *s1, const char *s2); + strcspn, + /// char *strdup(const char *s1); + strdup, + /// size_t strlen(const char *s); + strlen, + /// int strncasecmp(const char *s1, const char *s2, size_t n); + strncasecmp, + /// char *strncat(char *s1, const char *s2, size_t n); + strncat, + /// int strncmp(const char *s1, const char *s2, size_t n); + strncmp, + /// char *strncpy(char *s1, const char *s2, size_t n); + strncpy, + /// char *strndup(const char *s1, size_t n); + strndup, + /// size_t strnlen(const char *s, size_t maxlen); + strnlen, + /// char *strpbrk(const char *s1, const char *s2); + strpbrk, + /// char *strrchr(const char *s, int c); + strrchr, + /// size_t strspn(const char *s1, const char *s2); + strspn, + /// char *strstr(const char *s1, const char *s2); + strstr, + /// double strtod(const char *nptr, char **endptr); + strtod, + /// float strtof(const char *nptr, char **endptr); + strtof, + // char *strtok(char *s1, const char *s2); + strtok, + // char *strtok_r(char *s, const char *sep, char **lasts); + strtok_r, + /// long int strtol(const char *nptr, char **endptr, int base); + strtol, + /// long double strtold(const char *nptr, char **endptr); + strtold, + /// long long int strtoll(const char *nptr, char **endptr, int base); + strtoll, + /// unsigned long int strtoul(const char *nptr, char **endptr, int base); + strtoul, + /// unsigned long long int strtoull(const char *nptr, char **endptr, + /// int base); + strtoull, + /// size_t strxfrm(char *s1, const char *s2, size_t n); + strxfrm, + /// int system(const char *command); + system, + /// double tan(double x); + tan, + /// float tanf(float x); + tanf, + /// double tanh(double x); + tanh, + /// float tanhf(float x); + tanhf, + /// long double tanhl(long double x); + tanhl, + /// long double tanl(long double x); + tanl, + /// clock_t times(struct tms *buffer); + times, + /// FILE *tmpfile(void); + tmpfile, + /// FILE *tmpfile64(void) + tmpfile64, + /// int toascii(int c); + toascii, + /// double trunc(double x); + trunc, + /// float truncf(float x); + truncf, + /// long double truncl(long double x); + truncl, + /// int uname(struct utsname *name); + uname, + /// int ungetc(int c, FILE *stream); + ungetc, + /// int unlink(const char *path); + unlink, + /// int unsetenv(const char *name); + unsetenv, + /// int utime(const char *path, const struct utimbuf *times); + utime, + /// int utimes(const char *path, const struct timeval times[2]); + utimes, + /// void *valloc(size_t size); + valloc, + /// int vfprintf(FILE *stream, const char *format, va_list ap); + vfprintf, + /// int vfscanf(FILE *stream, const char *format, va_list arg); + vfscanf, + /// int vprintf(const char *restrict format, va_list ap); + vprintf, + /// int vscanf(const char *format, va_list arg); + vscanf, + /// int vsnprintf(char *s, size_t n, const char *format, va_list ap); + vsnprintf, + /// int vsprintf(char *s, const char *format, va_list ap); + vsprintf, + /// int vsscanf(const char *s, const char *format, va_list arg); + vsscanf, + /// ssize_t write(int fildes, const void *buf, size_t nbyte); + write, + + NumLibFuncs + }; + } + +/// \brief Implementation of the target library information. +/// +/// This class constructs tables that hold the target library information and +/// make it available. However, it is somewhat expensive to compute and only +/// depends on the triple. So users typicaly interact with the \c +/// TargetLibraryInfo wrapper below. +class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + + unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; + llvm::DenseMap CustomNames; + static const char* StandardNames[LibFunc::NumLibFuncs]; + + enum AvailabilityState { + StandardName = 3, // (memset to all ones) + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; + void setState(LibFunc::Func F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } + AvailabilityState getState(LibFunc::Func F) const { + return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + +public: + TargetLibraryInfoImpl(); + explicit TargetLibraryInfoImpl(const Triple &T); + + // Provide value semantics. + TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI); + TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI); + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; + + /// \brief Forces a function to be marked as unavailable. + void setUnavailable(LibFunc::Func F) { + setState(F, Unavailable); + } + + /// \brief Forces a function to be marked as available. + void setAvailable(LibFunc::Func F) { + setState(F, StandardName); + } + + /// \brief Forces a function to be marked as available and provide an + /// alternate name that must be used. + void setAvailableWithName(LibFunc::Func F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; + assert(CustomNames.find(F) != CustomNames.end()); + } else { + setState(F, StandardName); + } + } + + /// \brief Disables all builtins. + /// + /// This can be used for options like -fno-builtin. + void disableAllFunctions(); +}; + +/// \brief Provides information about what library functions are available for +/// the current target. +/// +/// This both allows optimizations to handle them specially and frontends to +/// disable such optimizations through -fno-builtin etc. +class TargetLibraryInfo { + friend class TargetLibraryAnalysis; + friend class TargetLibraryInfoWrapperPass; + + const TargetLibraryInfoImpl *Impl; + +public: + explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {} + + // Provide value semantics. + TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { + Impl = TLI.Impl; + return *this; + } + TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { + Impl = TLI.Impl; + return *this; + } + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { + return Impl->getLibFunc(funcName, F); + } + + /// \brief Tests wether a library function is available. + bool has(LibFunc::Func F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + + /// \brief Tests if the function is both available and a candidate for + /// optimized code generation. + bool hasOptimizedCodeGen(LibFunc::Func F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; + case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: + case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: + case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: + case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: + case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: + case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: + case LibFunc::sqrtl_finite: + case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: + case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: + case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: + case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: + case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: + case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: + case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: + case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: + case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: + case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: + case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: + case LibFunc::memchr: + return true; + } + return false; + } + + StringRef getName(LibFunc::Func F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); + if (State == TargetLibraryInfoImpl::StandardName) + return Impl->StandardNames[F]; + assert(State == TargetLibraryInfoImpl::CustomName); + return Impl->CustomNames.find(F)->second; + } + + /// \brief Handle invalidation from the pass manager. + /// + /// If we try to invalidate this info, just return false. It cannot become + /// invalid even if the module changes. + bool invalidate(Module &, const PreservedAnalyses &) { return false; } +}; + +/// \brief Analysis pass providing the \c TargetLibraryInfo. +/// +/// Note that this pass's result cannot be invalidated, it is immutable for the +/// life of the module. +class TargetLibraryAnalysis { +public: + typedef TargetLibraryInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Default construct the library analysis. + /// + /// This will use the module's triple to construct the library info for that + /// module. + TargetLibraryAnalysis() {} + + /// \brief Construct a library analysis with preset info. + /// + /// This will directly copy the preset info into the result without + /// consulting the module's triple. + TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl) + : PresetInfoImpl(std::move(PresetInfoImpl)) {} + + // Move semantics. We spell out the constructors for MSVC. + TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg) + : PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {} + TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) { + PresetInfoImpl = std::move(RHS.PresetInfoImpl); + Impls = std::move(RHS.Impls); + return *this; + } + + TargetLibraryInfo run(Module &M); + TargetLibraryInfo run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetLibraryAnalysis"; } + +private: + static char PassID; + + Optional PresetInfoImpl; + + StringMap> Impls; + + TargetLibraryInfoImpl &lookupInfoImpl(Triple T); +}; + +class TargetLibraryInfoWrapperPass : public ImmutablePass { + TargetLibraryInfoImpl TLIImpl; + TargetLibraryInfo TLI; + + virtual void anchor(); + +public: + static char ID; + TargetLibraryInfoWrapperPass(); + explicit TargetLibraryInfoWrapperPass(const Triple &T); + explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); + + TargetLibraryInfo &getTLI() { return TLI; } + const TargetLibraryInfo &getTLI() const { return TLI; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 9acaaa6..4998141 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -1,4 +1,4 @@ -//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===// +//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,22 +6,24 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This pass exposes codegen information to IR-level passes. Every -// transformation that uses codegen information is broken into three parts: -// 1. The IR-level analysis pass. -// 2. The IR-level transformation interface which provides the needed -// information. -// 3. Codegen-level implementation which uses target-specific hooks. -// -// This file defines #2, which is the interface that IR-level transformations -// use for querying the codegen. -// +/// \file +/// This pass exposes codegen information to IR-level passes. Every +/// transformation that uses codegen information is broken into three parts: +/// 1. The IR-level analysis pass. +/// 2. The IR-level transformation interface which provides the needed +/// information. +/// 3. Codegen-level implementation which uses target-specific hooks. +/// +/// This file defines #2, which is the interface that IR-level transformations +/// use for querying the codegen. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/ADT/Optional.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" @@ -31,41 +33,61 @@ namespace llvm { class Function; class GlobalValue; class Loop; +class PreservedAnalyses; class Type; class User; class Value; -/// TargetTransformInfo - This pass provides access to the codegen -/// interfaces that are needed for IR-level transformations. +/// \brief Information about a load/store intrinsic defined by the target. +struct MemIntrinsicInfo { + MemIntrinsicInfo() + : ReadMem(false), WriteMem(false), Vol(false), MatchingId(0), + NumMemRefs(0), PtrVal(nullptr) {} + bool ReadMem; + bool WriteMem; + bool Vol; + // Same Id is set by the target for corresponding load/store intrinsics. + unsigned short MatchingId; + int NumMemRefs; + Value *PtrVal; +}; + +/// \brief This pass provides access to the codegen interfaces that are needed +/// for IR-level transformations. class TargetTransformInfo { -protected: - /// \brief The TTI instance one level down the stack. +public: + /// \brief Construct a TTI object using a type implementing the \c Concept + /// API below. /// - /// This is used to implement the default behavior all of the methods which - /// is to delegate up through the stack of TTIs until one can answer the - /// query. - TargetTransformInfo *PrevTTI; + /// This is used by targets to construct a TTI wrapping their target-specific + /// implementaion that encodes appropriate costs for their target. + template TargetTransformInfo(T Impl); - /// \brief The top of the stack of TTI analyses available. + /// \brief Construct a baseline TTI object using a minimal implementation of + /// the \c Concept API below. /// - /// This is a convenience routine maintained as TTI analyses become available - /// that complements the PrevTTI delegation chain. When one part of an - /// analysis pass wants to query another part of the analysis pass it can use - /// this to start back at the top of the stack. - TargetTransformInfo *TopTTI; + /// The TTI implementation will reflect the information in the DataLayout + /// provided if non-null. + explicit TargetTransformInfo(const DataLayout *DL); - /// All pass subclasses must in their initializePass routine call - /// pushTTIStack with themselves to update the pointers tracking the previous - /// TTI instance in the analysis group's stack, and the top of the analysis - /// group's stack. - void pushTTIStack(Pass *P); + // Provide move semantics. + TargetTransformInfo(TargetTransformInfo &&Arg); + TargetTransformInfo &operator=(TargetTransformInfo &&RHS); - /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // We need to define the destructor out-of-line to define our sub-classes + // out-of-line. + ~TargetTransformInfo(); -public: - /// This class is intended to be subclassed by real implementations. - virtual ~TargetTransformInfo() = 0; + /// \brief Handle the invalidation of this information. + /// + /// When used as a result of \c TargetIRAnalysis this method will be called + /// when the function this was computed for changes. When it returns false, + /// the information is preserved across those changes. + bool invalidate(Function &, const PreservedAnalyses &) { + // FIXME: We should probably in some way ensure that the subtarget + // information for a function hasn't changed. + return false; + } /// \name Generic Target Information /// @{ @@ -86,9 +108,9 @@ public: /// skipped by renaming the registers in the CPU, but they still are encoded /// and thus wouldn't be considered 'free' here. enum TargetCostConstants { - TCC_Free = 0, ///< Expected to fold away in lowering. - TCC_Basic = 1, ///< The cost of a typical 'add' instruction. - TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. + TCC_Free = 0, ///< Expected to fold away in lowering. + TCC_Basic = 1, ///< The cost of a typical 'add' instruction. + TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. }; /// \brief Estimate the cost of a specific operation when lowered. @@ -105,16 +127,15 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, - Type *OpTy = nullptr) const; + unsigned getOperationCost(unsigned Opcode, Type *Ty, + Type *OpTy = nullptr) const; /// \brief Estimate the cost of a GEP operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the GEP operation. - virtual unsigned getGEPCost(const Value *Ptr, - ArrayRef Operands) const; + unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) const; /// \brief Estimate the cost of a function call when lowered. /// @@ -125,31 +146,31 @@ public: /// This is the most basic query for estimating call cost: it only knows the /// function type and (potentially) the number of arguments at the call site. /// The latter is only interesting for varargs function types. - virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; + unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. - virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const; + unsigned getCallCost(const Function *F, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. - virtual unsigned getCallCost(const Function *F, - ArrayRef Arguments) const; + unsigned getCallCost(const Function *F, + ArrayRef Arguments) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef ParamTys) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef Arguments) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) const; /// \brief Estimate the cost of a given IR user when lowered. /// @@ -166,13 +187,13 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getUserCost(const User *U) const; + 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; + bool hasBranchDivergence() const; /// \brief Test whether calls to a function lower to actual program function /// calls. @@ -186,7 +207,7 @@ public: /// and execution-speed costs. This would allow modelling the core of this /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. - virtual bool isLoweredToCall(const Function *F) const; + bool isLoweredToCall(const Function *F) const; /// Parameters that control the generic loop unrolling transformation. struct UnrollingPreferences { @@ -196,6 +217,13 @@ public: /// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// restriction. unsigned Threshold; + /// If complete unrolling could help other optimizations (e.g. InstSimplify) + /// to remove N% of instructions, then we can go beyond unroll threshold. + /// This value set the minimal percent for allowing that. + unsigned MinPercentOfOptimized; + /// The absolute cost threshold. We won't go beyond this even if complete + /// unrolling could result in optimizing out 90% of instructions. + unsigned AbsoluteThreshold; /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; @@ -203,8 +231,8 @@ public: /// for partial/runtime unrolling (set to UINT_MAX to disable). unsigned PartialThreshold; /// The cost threshold for the unrolled loop when optimizing for size, like - /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX - /// to disable). + /// OptSizeThreshold, but used for partial/runtime unrolling (set to + /// UINT_MAX to disable). unsigned PartialOptSizeThreshold; /// A forced unrolling factor (the number of concatenated bodies of the /// original loop in the unrolled loop body). When set to 0, the unrolling @@ -218,18 +246,17 @@ public: unsigned MaxCount; /// 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; + 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; + /// 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(const Function *F, Loop *L, - UnrollingPreferences &UP) const; + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; /// @} @@ -244,31 +271,33 @@ public: /// support is considered as "Fast" if it can outperform, or is on a par /// with, SW implementation when the population is sparse; otherwise, it is /// considered as "Slow". - enum PopcntSupportKind { - PSK_Software, - PSK_SlowHardware, - PSK_FastHardware - }; + enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware }; /// \brief Return true if the specified immediate is legal add immediate, that /// is the target has add instructions which can add a register with the /// immediate without having to materialize the immediate into a register. - virtual bool isLegalAddImmediate(int64_t Imm) const; + bool isLegalAddImmediate(int64_t Imm) const; /// \brief Return true if the specified immediate is legal icmp immediate, /// that is the target has icmp instructions which can compare a register /// against the immediate without having to materialize the immediate into a /// register. - virtual bool isLegalICmpImmediate(int64_t Imm) const; + bool isLegalICmpImmediate(int64_t Imm) const; /// \brief Return true if the addressing mode represented by AM is legal for /// this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. - virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; + + /// \brief Return true if the target works with masked instruction + /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. + /// AVX-512 architecture will also allow masks for non-consecutive memory + /// accesses. + bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + bool isLegalMaskedLoad(Type *DataType, int Consecutive) const; /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store @@ -276,45 +305,52 @@ public: /// 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; + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief Return true if it's free to truncate a value of type Ty1 to type /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. - virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + bool isTruncateFree(Type *Ty1, Type *Ty2) const; + + /// \brief Return true if it is profitable to hoist instruction in the + /// then/else to before if. + bool isProfitableToHoist(Instruction *I) const; /// \brief Return true if this type is legal. - virtual bool isTypeLegal(Type *Ty) const; + bool isTypeLegal(Type *Ty) const; /// \brief Returns the target's jmp_buf alignment in bytes. - virtual unsigned getJumpBufAlignment() const; + unsigned getJumpBufAlignment() const; /// \brief Returns the target's jmp_buf size in bytes. - virtual unsigned getJumpBufSize() const; + unsigned getJumpBufSize() const; /// \brief Return true if switches should be turned into lookup tables for the /// target. - virtual bool shouldBuildLookupTables() const; + bool shouldBuildLookupTables() const; /// \brief Return hardware support for population count. - virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; /// \brief Return true if the hardware has a fast square-root instruction. - virtual bool haveFastSqrt(Type *Ty) const; + bool haveFastSqrt(Type *Ty) const; + + /// \brief Return the expected cost of supporting the floating point operation + /// of the specified type. + unsigned getFPOpCost(Type *Ty) const; /// \brief Return the expected cost of materializing for the given integer /// immediate of the specified type. - virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; /// \brief Return the expected cost of materialization for the given integer /// immediate of the specified type for a given instruction. The cost can be /// zero if the immediate can be folded into the specified instruction. - virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty) const; - virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, - const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) const; + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) const; /// @} /// \name Vector Target Information @@ -331,10 +367,10 @@ public: /// \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). - OK_UniformConstantValue, // Operand is uniform constant. - OK_NonUniformConstantValue // Operand is a non uniform constant value. + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue, // Operand is uniform constant. + OK_NonUniformConstantValue // Operand is a non uniform constant value. }; /// \brief Additional properties of an operand's values. @@ -343,18 +379,18 @@ public: /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. - virtual unsigned getNumberOfRegisters(bool Vector) const; + unsigned getNumberOfRegisters(bool Vector) const; /// \return The width of the largest scalar or vector register type. - virtual unsigned getRegisterBitWidth(bool Vector) const; + unsigned getRegisterBitWidth(bool Vector) const; /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaxInterleaveFactor() const; + unsigned getMaxInterleaveFactor() const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, @@ -364,31 +400,33 @@ public: /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. - virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, - Type *SubTp = nullptr) const; + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = nullptr) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. - virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const; + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const; /// \return The expected cost of control-flow related instructions such as /// Phi, Ret, Br. - virtual unsigned getCFInstrCost(unsigned Opcode) const; + unsigned getCFInstrCost(unsigned Opcode) const; /// \returns The expected cost of compare and select instructions. - virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = nullptr) const; + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = nullptr) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. - virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index = -1) const; + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const; /// \return The cost of Load and Store instructions. - virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, - unsigned Alignment, - unsigned AddressSpace) const; + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; + + /// \return The cost of masked Load and Store instructions. + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; /// \brief Calculate the cost of performing a vector reduction. /// @@ -403,16 +441,16 @@ public: /// Split: /// (v0, v1, v2, v3) /// ((v0+v2), (v1+v3), undef, undef) - virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, - bool IsPairwiseForm) const; + 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; + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) const; /// \returns The number of pieces into which the provided type must be /// split during legalization. Zero is returned when the answer is unknown. - virtual unsigned getNumberOfParts(Type *Tp) const; + unsigned getNumberOfParts(Type *Tp) const; /// \returns The cost of the address computation. For most targets this can be /// merged into the instruction indexing mode. Some targets might want to @@ -421,28 +459,385 @@ public: /// 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; + unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; /// \returns The cost, if any, of keeping values of the given types alive /// over a callsite. /// /// Some types may require the use of register classes that do not have /// any callee-saved registers, so would require a spill and fill. - virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const; + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const; + + /// \returns True if the intrinsic is a supported memory intrinsic. Info + /// will contain additional information - whether the intrinsic may write + /// or read to memory, volatility and the pointer. Info is undefined + /// if false is returned. + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const; + + /// \returns A value which is the result of the given memory intrinsic. New + /// instructions may be created to extract the result from the given intrinsic + /// memory operation. Returns nullptr if the target cannot create a result + /// from the given intrinsic. + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) const; /// @} - /// Analysis group identification. +private: + /// \brief The abstract base class used to type erase specific TTI + /// implementations. + class Concept; + + /// \brief The template model for the base class which wraps a concrete + /// implementation in a type erased interface. + template class Model; + + std::unique_ptr TTIImpl; +}; + +class TargetTransformInfo::Concept { +public: + virtual ~Concept() = 0; + + virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; + virtual unsigned getGEPCost(const Value *Ptr, + ArrayRef Operands) = 0; + virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, + ArrayRef Arguments) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) = 0; + virtual unsigned getUserCost(const User *U) = 0; + virtual bool hasBranchDivergence() = 0; + virtual bool isLoweredToCall(const Function *F) = 0; + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; + virtual bool isLegalAddImmediate(int64_t Imm) = 0; + virtual bool isLegalICmpImmediate(int64_t Imm) = 0; + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0; + virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0; + virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; + virtual bool isProfitableToHoist(Instruction *I) = 0; + virtual bool isTypeLegal(Type *Ty) = 0; + virtual unsigned getJumpBufAlignment() = 0; + virtual unsigned getJumpBufSize() = 0; + virtual bool shouldBuildLookupTables() = 0; + virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0; + virtual bool haveFastSqrt(Type *Ty) = 0; + virtual unsigned getFPOpCost(Type *Ty) = 0; + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0; + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) = 0; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) = 0; + virtual unsigned getNumberOfRegisters(bool Vector) = 0; + virtual unsigned getRegisterBitWidth(bool Vector) = 0; + virtual unsigned getMaxInterleaveFactor() = 0; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) = 0; + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) = 0; + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0; + virtual unsigned getCFInstrCost(unsigned Opcode) = 0; + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) = 0; + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) = 0; + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) = 0; + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) = 0; + virtual unsigned getNumberOfParts(Type *Tp) = 0; + virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0; + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) = 0; + virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) = 0; + virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) = 0; +}; + +template +class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { + T Impl; + +public: + Model(T Impl) : Impl(std::move(Impl)) {} + ~Model() override {} + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { + return Impl.getOperationCost(Opcode, Ty, OpTy); + } + unsigned getGEPCost(const Value *Ptr, + ArrayRef Operands) override { + return Impl.getGEPCost(Ptr, Operands); + } + unsigned getCallCost(FunctionType *FTy, int NumArgs) override { + return Impl.getCallCost(FTy, NumArgs); + } + unsigned getCallCost(const Function *F, int NumArgs) override { + return Impl.getCallCost(F, NumArgs); + } + unsigned getCallCost(const Function *F, + ArrayRef Arguments) override { + return Impl.getCallCost(F, Arguments); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) override { + return Impl.getIntrinsicCost(IID, RetTy, ParamTys); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) override { + return Impl.getIntrinsicCost(IID, RetTy, Arguments); + } + unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); } + bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); } + bool isLoweredToCall(const Function *F) override { + return Impl.isLoweredToCall(F); + } + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override { + return Impl.getUnrollingPreferences(L, UP); + } + bool isLegalAddImmediate(int64_t Imm) override { + return Impl.isLegalAddImmediate(Imm); + } + bool isLegalICmpImmediate(int64_t Imm) override { + return Impl.isLegalICmpImmediate(Imm); + } + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, + Scale); + } + bool isLegalMaskedStore(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedStore(DataType, Consecutive); + } + bool isLegalMaskedLoad(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedLoad(DataType, Consecutive); + } + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale); + } + bool isTruncateFree(Type *Ty1, Type *Ty2) override { + return Impl.isTruncateFree(Ty1, Ty2); + } + bool isProfitableToHoist(Instruction *I) override { + return Impl.isProfitableToHoist(I); + } + bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } + unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); } + unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); } + bool shouldBuildLookupTables() override { + return Impl.shouldBuildLookupTables(); + } + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override { + return Impl.getPopcntSupport(IntTyWidthInBit); + } + bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); } + + unsigned getFPOpCost(Type *Ty) override { + return Impl.getFPOpCost(Ty); + } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) override { + return Impl.getIntImmCost(Imm, Ty); + } + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(Opc, Idx, Imm, Ty); + } + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(IID, Idx, Imm, Ty); + } + unsigned getNumberOfRegisters(bool Vector) override { + return Impl.getNumberOfRegisters(Vector); + } + unsigned getRegisterBitWidth(bool Vector) override { + return Impl.getRegisterBitWidth(Vector); + } + unsigned getMaxInterleaveFactor() override { + return Impl.getMaxInterleaveFactor(); + } + unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) override { + return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo); + } + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) override { + return Impl.getShuffleCost(Kind, Tp, Index, SubTp); + } + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override { + return Impl.getCastInstrCost(Opcode, Dst, Src); + } + unsigned getCFInstrCost(unsigned Opcode) override { + return Impl.getCFInstrCost(Opcode); + } + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) override { + return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy); + } + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) override { + return Impl.getVectorInstrCost(Opcode, Val, Index); + } + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) override { + return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm); + } + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) override { + return Impl.getIntrinsicInstrCost(ID, RetTy, Tys); + } + unsigned getNumberOfParts(Type *Tp) override { + return Impl.getNumberOfParts(Tp); + } + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override { + return Impl.getAddressComputationCost(Ty, IsComplex); + } + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) override { + return Impl.getCostOfKeepingLiveOverCall(Tys); + } + bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) override { + return Impl.getTgtMemIntrinsic(Inst, Info); + } + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) override { + return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType); + } +}; + +template +TargetTransformInfo::TargetTransformInfo(T Impl) + : TTIImpl(new Model(Impl)) {} + +/// \brief Analysis pass providing the \c TargetTransformInfo. +/// +/// The core idea of the TargetIRAnalysis is to expose an interface through +/// which LLVM targets can analyze and provide information about the middle +/// end's target-independent IR. This supports use cases such as target-aware +/// cost modeling of IR constructs. +/// +/// This is a function analysis because much of the cost modeling for targets +/// is done in a subtarget specific way and LLVM supports compiling different +/// functions targeting different subtargets in order to support runtime +/// dispatch according to the observed subtarget. +class TargetIRAnalysis { +public: + typedef TargetTransformInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetIRAnalysis"; } + + /// \brief Default construct a target IR analysis. + /// + /// This will use the module's datalayout to construct a baseline + /// conservative TTI result. + TargetIRAnalysis(); + + /// \brief Construct an IR analysis pass around a target-provide callback. + /// + /// The callback will be called with a particular function for which the TTI + /// is needed and must return a TTI object for that function. + TargetIRAnalysis(std::function TTICallback); + + // Value semantics. We spell out the constructors for MSVC. + TargetIRAnalysis(const TargetIRAnalysis &Arg) + : TTICallback(Arg.TTICallback) {} + TargetIRAnalysis(TargetIRAnalysis &&Arg) + : TTICallback(std::move(Arg.TTICallback)) {} + TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) { + TTICallback = RHS.TTICallback; + return *this; + } + TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) { + TTICallback = std::move(RHS.TTICallback); + return *this; + } + + Result run(Function &F); + +private: + static char PassID; + + /// \brief The callback used to produce a result. + /// + /// We use a completely opaque callback so that targets can provide whatever + /// mechanism they desire for constructing the TTI for a given function. + /// + /// FIXME: Should we really use std::function? It's relatively inefficient. + /// It might be possible to arrange for even stateful callbacks to outlive + /// the analysis and thus use a function_ref which would be lighter weight. + /// This may also be less error prone as the callback is likely to reference + /// the external TargetMachine, and that reference needs to never dangle. + std::function TTICallback; + + /// \brief Helper function used as the callback in the default constructor. + static Result getDefaultTTI(Function &F); +}; + +/// \brief Wrapper pass for TargetTransformInfo. +/// +/// This pass can be constructed from a TTI object which it stores internally +/// and is queried by passes. +class TargetTransformInfoWrapperPass : public ImmutablePass { + TargetIRAnalysis TIRA; + Optional TTI; + + virtual void anchor(); + +public: static char ID; + + /// \brief We must provide a default constructor for the pass but it should + /// never be used. + /// + /// Use the constructor below or call one of the creation routines. + TargetTransformInfoWrapperPass(); + + explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); + + TargetTransformInfo &getTTI(Function &F); }; -/// \brief Create the base case instance of a pass in the TTI analysis group. +/// \brief Create an analysis pass wrapper around a TTI object. /// -/// This class provides the base case for the stack of TTI analyzes. It doesn't -/// delegate to anything and uses the STTI and VTTI objects passed in to -/// satisfy the queries. -ImmutablePass *createNoTargetTransformInfoPass(); +/// This analysis pass just holds the TTI instance and makes it available to +/// clients. +ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); } // End llvm namespace diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h new file mode 100644 index 0000000..3e02c0c --- /dev/null +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -0,0 +1,433 @@ +//===- TargetTransformInfoImpl.h --------------------------------*- 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 helpers for the implementation of +/// a TargetTransformInfo-conforming class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H +#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H + +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" + +namespace llvm { + +/// \brief Base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +class TargetTransformInfoImplBase { +protected: + typedef TargetTransformInfo TTI; + + const DataLayout *DL; + + explicit TargetTransformInfoImplBase(const DataLayout *DL) + : DL(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) + : DL(Arg.DL) {} + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) + : DL(std::move(Arg.DL)) {} + TargetTransformInfoImplBase & + operator=(const TargetTransformInfoImplBase &RHS) { + DL = RHS.DL; + return *this; + } + TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { + DL = std::move(RHS.DL); + return *this; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + switch (Opcode) { + default: + // By default, just classify everything as 'basic'. + return TTI::TCC_Basic; + + case Instruction::GetElementPtr: + llvm_unreachable("Use getGEPCost for GEP operations!"); + + case Instruction::BitCast: + assert(OpTy && "Cast instructions must provide the operand type"); + if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy())) + // Identity and pointer-to-pointer casts are free. + return TTI::TCC_Free; + + // Otherwise, the default basic cost is used. + return TTI::TCC_Basic; + + case Instruction::IntToPtr: { + if (!DL) + return TTI::TCC_Basic; + + // An inttoptr cast is free so long as the input is a legal integer type + // which doesn't contain values outside the range of a pointer. + unsigned OpSize = OpTy->getScalarSizeInBits(); + if (DL->isLegalInteger(OpSize) && + OpSize <= DL->getPointerTypeSizeInBits(Ty)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::PtrToInt: { + if (!DL) + return TTI::TCC_Basic; + + // A ptrtoint cast is free so long as the result is large enough to store + // the pointer, and a legal integer type. + unsigned DestSize = Ty->getScalarSizeInBits(); + if (DL->isLegalInteger(DestSize) && + DestSize >= DL->getPointerTypeSizeInBits(OpTy)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::Trunc: + // trunc to a native type is free (assuming the target has compare and + // shift-right of the same width). + if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty))) + return TTI::TCC_Free; + + return TTI::TCC_Basic; + } + } + + unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) { + // In the basic model, we just assume that all-constant GEPs will be folded + // into their uses via addressing modes. + for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) + if (!isa(Operands[Idx])) + return TTI::TCC_Basic; + + return TTI::TCC_Free; + } + + unsigned getCallCost(FunctionType *FTy, int NumArgs) { + assert(FTy && "FunctionType must be provided to this routine."); + + // The target-independent implementation just measures the size of the + // function by approximating that each argument will take on average one + // instruction to prepare. + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = FTy->getNumParams(); + + return TTI::TCC_Basic * (NumArgs + 1); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) { + switch (IID) { + default: + // Intrinsics rarely (if ever) have normal argument setup constraints. + // Model them as having a basic instruction cost. + // FIXME: This is wrong for libc intrinsics. + return TTI::TCC_Basic; + + case Intrinsic::annotation: + case Intrinsic::assume: + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::objectsize: + case Intrinsic::ptr_annotation: + case Intrinsic::var_annotation: + case Intrinsic::experimental_gc_result_int: + case Intrinsic::experimental_gc_result_float: + case Intrinsic::experimental_gc_result_ptr: + case Intrinsic::experimental_gc_result: + case Intrinsic::experimental_gc_relocate: + // These intrinsics don't actually represent code after lowering. + return TTI::TCC_Free; + } + } + + bool hasBranchDivergence() { return false; } + + bool isLoweredToCall(const Function *F) { + // FIXME: These should almost certainly not be handled here, and instead + // handled with the help of TLI or the target itself. This was largely + // ported from existing analysis heuristics here so that such refactorings + // can take place in the future. + + if (F->isIntrinsic()) + return false; + + if (F->hasLocalLinkage() || !F->hasName()) + return true; + + StringRef Name = F->getName(); + + // These will all likely lower to a single selection DAG node. + if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" || + Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" || + Name == "fmin" || Name == "fminf" || Name == "fminl" || + Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" || + Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" || + Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") + return false; + + // These are all likely to be optimized into something smaller. + if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" || + Name == "exp2l" || Name == "exp2f" || Name == "floor" || + Name == "floorf" || Name == "ceil" || Name == "round" || + Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" || + Name == "llabs") + return false; + + return true; + } + + void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {} + + bool isLegalAddImmediate(int64_t Imm) { return false; } + + bool isLegalICmpImmediate(int64_t Imm) { return false; } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that reg+reg addressing is allowed. This heuristic is taken from + // the implementation of LSR. + return !BaseGV && BaseOffset == 0 && Scale <= 1; + } + + bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; } + + bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that all legal addressing mode are free. + if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale)) + return 0; + return -1; + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } + + bool isProfitableToHoist(Instruction *I) { return true; } + + bool isTypeLegal(Type *Ty) { return false; } + + unsigned getJumpBufAlignment() { return 0; } + + unsigned getJumpBufSize() { return 0; } + + bool shouldBuildLookupTables() { return true; } + + TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) { + return TTI::PSK_Software; + } + + bool haveFastSqrt(Type *Ty) { return false; } + + unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; } + + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getNumberOfRegisters(bool Vector) { return 8; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor() { return 1; } + + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info, + TTI::OperandValueKind Opd2Info, + TTI::OperandValueProperties Opd1PropInfo, + TTI::OperandValueProperties Opd2PropInfo) { + return 1; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index, + Type *SubTp) { + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; } + + unsigned getCFInstrCost(unsigned Opcode) { return 1; } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + return 1; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) { + return 1; + } + + unsigned getNumberOfParts(Type *Tp) { return 0; } + + unsigned getAddressComputationCost(Type *Tp, bool) { return 0; } + + unsigned getReductionCost(unsigned, Type *, bool) { return 1; } + + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) { return 0; } + + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) { + return false; + } + + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) { + return nullptr; + } +}; + +/// \brief CRTP base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +template +class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { +private: + typedef TargetTransformInfoImplBase BaseT; + +protected: + explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) + : BaseT(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg) + : BaseT(static_cast(Arg)) {} + TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) + : BaseT(std::move(static_cast(Arg))) {} + TargetTransformInfoImplCRTPBase & + operator=(const TargetTransformInfoImplCRTPBase &RHS) { + BaseT::operator=(static_cast(RHS)); + return *this; + } + TargetTransformInfoImplCRTPBase & + operator=(TargetTransformInfoImplCRTPBase &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; + } + + using BaseT::getCallCost; + + unsigned getCallCost(const Function *F, int NumArgs) { + assert(F && "A concrete function must be provided to this routine."); + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = F->arg_size(); + + if (Intrinsic::ID IID = (Intrinsic::ID)F->getIntrinsicID()) { + FunctionType *FTy = F->getFunctionType(); + SmallVector ParamTys(FTy->param_begin(), FTy->param_end()); + return static_cast(this) + ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys); + } + + if (!static_cast(this)->isLoweredToCall(F)) + return TTI::TCC_Basic; // Give a basic cost if it will be lowered + // directly. + + return static_cast(this)->getCallCost(F->getFunctionType(), NumArgs); + } + + unsigned getCallCost(const Function *F, ArrayRef Arguments) { + // Simply delegate to generic handling of the call. + // FIXME: We should use instsimplify or something else to catch calls which + // will constant fold with these arguments. + return static_cast(this)->getCallCost(F, Arguments.size()); + } + + using BaseT::getIntrinsicCost; + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) { + // Delegate to the generic intrinsic handling code. This mostly provides an + // opportunity for targets to (for example) special case the cost of + // certain intrinsics based on constants used as arguments. + SmallVector ParamTys; + ParamTys.reserve(Arguments.size()); + for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) + ParamTys.push_back(Arguments[Idx]->getType()); + return static_cast(this)->getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getUserCost(const User *U) { + if (isa(U)) + return TTI::TCC_Free; // Model all PHI nodes as free. + + if (const GEPOperator *GEP = dyn_cast(U)) { + SmallVector Indices(GEP->idx_begin(), GEP->idx_end()); + return static_cast(this) + ->getGEPCost(GEP->getPointerOperand(), Indices); + } + + if (ImmutableCallSite CS = U) { + const Function *F = CS.getCalledFunction(); + if (!F) { + // Just use the called value type. + Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); + return static_cast(this) + ->getCallCost(cast(FTy), CS.arg_size()); + } + + SmallVector Arguments(CS.arg_begin(), CS.arg_end()); + return static_cast(this)->getCallCost(F, Arguments); + } + + if (const CastInst *CI = dyn_cast(U)) { + // Result of a cmp instruction is often extended (to be used by other + // cmp instructions, logical or return instructions). These are usually + // nop on most sane targets. + if (isa(CI->getOperand(0))) + return TTI::TCC_Free; + } + + return static_cast(this)->getOperationCost( + Operator::getOpcode(U), U->getType(), + U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); + } +}; +} + +#endif diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 6bbf4f4..ac8c3b7 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,7 +25,7 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class TargetLibraryInfo; @@ -37,9 +37,9 @@ namespace llvm { /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, + void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); /// Compute known bits from the range metadata. @@ -51,7 +51,7 @@ namespace llvm { /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -61,7 +61,7 @@ namespace llvm { /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -70,7 +70,7 @@ namespace llvm { /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, - unsigned Depth = 0, AssumptionTracker *AT = nullptr, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -83,13 +83,12 @@ namespace llvm { /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, + bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); - /// ComputeNumSignBits - Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us @@ -99,8 +98,7 @@ namespace llvm { /// 'Op' must have a scalar integer type. /// unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, - unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -118,6 +116,11 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + /// CannotBeOrderedLessThanZero - Return true if we can prove that the + /// specified FP value is either a NaN or never less than 0.0. + /// + bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0); + /// isBytewiseValue - If the specified value can be set by repeating the same /// byte in memory, return the i8 value that it is represented with. This is /// true for all i8 values obviously, but is also true for i32 0, i32 -1, @@ -217,6 +220,17 @@ namespace llvm { const DataLayout *DL = nullptr, const DominatorTree *DT = nullptr); + enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; + OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); + OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); } // end namespace llvm #endif diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index ed2dcf8..3f7a77d 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -125,7 +125,7 @@ public: case Blob: return false; } - llvm_unreachable("Invalid encoding"); + report_fatal_error("Invalid encoding"); } /// isChar6 - Return true if this character is legal in the Char6 encoding. diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index eb85548..8fe9b7e 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -41,7 +41,7 @@ public: /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "BitcodeWriterPass"; } }; diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index ecf8235..c20a160 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -50,8 +50,8 @@ private: /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; - BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; - void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; + BitstreamReader(const BitstreamReader&) = delete; + void operator=(const BitstreamReader&) = delete; public: BitstreamReader() : IgnoreBlockInfoNames(true) { } @@ -61,9 +61,8 @@ public: init(Start, End); } - BitstreamReader(MemoryObject *bytes) : IgnoreBlockInfoNames(true) { - BitcodeBytes.reset(bytes); - } + BitstreamReader(std::unique_ptr BitcodeBytes) + : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {} BitstreamReader(BitstreamReader &&Other) { *this = std::move(Other); @@ -259,8 +258,8 @@ public: AF_DontAutoprocessAbbrevs = 2 }; - /// Advance the current bitstream, returning the next entry in the stream. - BitstreamEntry advance(unsigned Flags = 0) { + /// Advance the current bitstream, returning the next entry in the stream. + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { @@ -302,7 +301,7 @@ public: /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -316,7 +315,8 @@ public: } void fillCurWord() { - assert(Size == 0 || NextChar < (unsigned)Size); + if (Size != 0 && NextChar >= Size) + report_fatal_error("Unexpected end of file"); // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; @@ -491,11 +491,11 @@ private: //===--------------------------------------------------------------------===// public: - /// Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { - unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; - assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; + if (AbbrevNo >= CurAbbrevs.size()) + report_fatal_error("Invalid abbrev number"); return CurAbbrevs[AbbrevNo].get(); } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index c42ecfe..d842167 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -137,16 +137,36 @@ namespace bitc { enum MetadataCodes { METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. + METADATA_VALUE = 2, // VALUE: [type num, value num] + METADATA_NODE = 3, // NODE: [n x md num] METADATA_NAME = 4, // STRING: [values] - // 5 is unused. + METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num] METADATA_KIND = 6, // [n x [id, name]] - // 7 is unused. - METADATA_NODE = 8, // NODE: [n x (type num, value num)] - METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)] + METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?] + METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)] + METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)] METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] - METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] + METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]] + METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] + METADATA_SUBRANGE = 13, // [distinct, count, lo] + METADATA_ENUMERATOR = 14, // [distinct, value, name] + METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] + METADATA_FILE = 16, // [distinct, filename, directory] + METADATA_DERIVED_TYPE = 17, // [distinct, ...] + METADATA_COMPOSITE_TYPE= 18, // [distinct, ...] + METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types] + METADATA_COMPILE_UNIT = 20, // [distinct, ...] + METADATA_SUBPROGRAM = 21, // [distinct, ...] + METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column] + METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator] + METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line] + METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...] + METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...] + METADATA_GLOBAL_VAR = 27, // [distinct, ...] + METADATA_LOCAL_VAR = 28, // [distinct, ...] + METADATA_EXPRESSION = 29, // [distinct, n x element] + METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...] + METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -273,7 +293,7 @@ namespace bitc { FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] - FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands] FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] @@ -307,7 +327,7 @@ namespace bitc { FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] // new select on i1 or [N x i1] FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] - FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands] FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...] // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN @@ -325,8 +345,9 @@ namespace bitc { FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, // ordering, synchscope] - FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_STOREATOMIC = 42, // STORE: [ptrty,ptr,val, align, vol // ordering, synchscope] + FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] }; enum UseListCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 2e8cdc7..48bdabc 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -14,6 +14,7 @@ #ifndef LLVM_BITCODE_READERWRITER_H #define LLVM_BITCODE_READERWRITER_H +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -30,27 +31,28 @@ namespace llvm { /// Read the header of the specified bitcode buffer and prepare for lazy /// deserialization of function bodies. If successful, this moves Buffer. On /// error, this *does not* move Buffer. - ErrorOr getLazyBitcodeModule(std::unique_ptr &&Buffer, - LLVMContext &Context); - - /// getStreamedBitcodeModule - Read the header of the specified stream - /// and prepare for lazy deserialization and streaming of function bodies. - /// On error, this returns null, and fills in *ErrMsg with an error - /// description if ErrMsg is non-null. - Module *getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, - LLVMContext &Context, - std::string *ErrMsg = nullptr); + ErrorOr + getLazyBitcodeModule(std::unique_ptr &&Buffer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the header of the specified stream and prepare for lazy + /// deserialization and streaming of function bodies. + ErrorOr> getStreamedBitcodeModule( + StringRef Name, DataStreamer *Streamer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the header of the specified bitcode buffer and extract just the /// triple information. If successful, this returns a string. On error, this /// returns "". - std::string getBitcodeTargetTriple(MemoryBufferRef Buffer, - LLVMContext &Context); + std::string + getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the specified bitcode file, returning the module. - ErrorOr parseBitcodeFile(MemoryBufferRef Buffer, - LLVMContext &Context); + ErrorOr + parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// WriteBitcodeToFile - Write the specified module to the specified /// raw output stream. For streams where it matters, the given stream @@ -141,32 +143,26 @@ namespace llvm { } const std::error_category &BitcodeErrorCategory(); - enum class BitcodeError { - ConflictingMETADATA_KINDRecords, - CouldNotFindFunctionInStream, - ExpectedConstant, - InsufficientFunctionProtos, - InvalidBitcodeSignature, - InvalidBitcodeWrapperHeader, - InvalidConstantReference, - InvalidID, // A read identifier is not found in the table it should be in. - InvalidInstructionWithNoBB, - InvalidRecord, // A read record doesn't have the expected size or structure - InvalidTypeForValue, // Type read OK, but is invalid for its use - InvalidTYPETable, - InvalidType, // We were unable to read a type - MalformedBlock, // We are unable to advance in the stream. - MalformedGlobalInitializerSet, - InvalidMultipleBlocks, // We found multiple blocks of a kind that should - // have only one - NeverResolvedValueFoundInFunction, - NeverResolvedFunctionFromBlockAddress, - InvalidValue // Invalid version, inst number, attr number, etc - }; + enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; inline std::error_code make_error_code(BitcodeError E) { return std::error_code(static_cast(E), BitcodeErrorCategory()); } + class BitcodeDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + std::error_code EC; + + public: + BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, + const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + std::error_code getError() const { return EC; }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Bitcode; + } + }; + } // End llvm namespace namespace std { diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 3132999..c4b94ed 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -31,10 +31,21 @@ class SDValue; class SelectionDAG; struct EVT; -/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence -/// of insertvalue or extractvalue indices that identify a member, return -/// the linearized index of the start of the member. +/// \brief Compute the linearized index of a member in a nested +/// aggregate/struct/array. /// +/// Given an LLVM IR aggregate type and a sequence of insertvalue or +/// extractvalue indices that identify a member, return the linearized index of +/// the start of the member, i.e the number of element in memory before the +/// seeked one. This is disconnected from the number of bytes. +/// +/// \param Ty is the type indexed by \p Indices. +/// \param Indices is an optional pointer in the indices list to the current +/// index. +/// \param IndicesEnd is the end of the indices list. +/// \param CurIndex is the current index in the recursion. +/// +/// \returns \p CurIndex plus the linear index in \p Ty the indices list. unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 25b99a2..ac224d8 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -44,8 +44,8 @@ class MachineModuleInfo; class MCAsmInfo; class MCCFIInstruction; class MCContext; +class MCExpr; class MCInst; -class MCInstrInfo; class MCSection; class MCStreamer; class MCSubtargetInfo; @@ -68,7 +68,6 @@ public: /// const MCAsmInfo *MAI; - const MCInstrInfo *MII; /// This is the context for the output file that we are streaming. This owns /// all of the global MC-related objects for the generated translation unit. MCContext &OutContext; @@ -98,6 +97,11 @@ public: /// default, this is equal to CurrentFnSym. MCSymbol *CurrentFnSymForSize; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of + /// its number of uses by other globals. + typedef std::pair GOTEquivUsePair; + DenseMap GlobalGOTEquivs; + private: // The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -126,12 +130,13 @@ private: DwarfDebug *DD; protected: - explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); + explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); public: virtual ~AsmPrinter(); DwarfDebug *getDwarfDebug() { return DD; } + DwarfDebug *getDwarfDebug() const { return DD; } /// Return true if assembly output should contain comments. /// @@ -203,6 +208,8 @@ public: void emitCFIInstruction(const MachineInstr &MI); + void emitFrameAlloc(const MachineInstr &MI); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); @@ -234,13 +241,27 @@ public: /// void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; - /// This method prints the label for the specified MachineBasicBlock, an - /// alignment (if present) and a comment describing it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Lower the specified LLVM Constant to an MCExpr. + const MCExpr *lowerConstant(const Constant *CV); /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); + /// \brief Unnamed constant global variables solely contaning a pointer to + /// another globals variable act like a global variable "proxy", or GOT + /// equivalents, i.e., it's only used to hold the address of the latter. One + /// optimization is to replace accesses to these proxies by using the GOT + /// entry for the final global instead. Hence, we select GOT equivalent + /// candidates among all the module global variables, avoid emitting them + /// unnecessarily and finally replace references to them by pc relative + /// accesses to GOT entries. + void computeGlobalGOTEquivs(Module &M); + + /// \brief Constant expressions using GOT equivalent globals may not be + /// eligible for PC relative GOT entry conversion, in such cases we need to + /// emit the proxies we previously omitted in EmitGlobalVariable. + void emitGlobalGOTEquivs(); + //===------------------------------------------------------------------===// // Overridable Hooks //===------------------------------------------------------------------===// @@ -264,6 +285,12 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the start of a basic block. + /// By default, this method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing it + /// if appropriate. + virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Targets can override this to emit stuff at the end of a basic block. virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} @@ -299,10 +326,10 @@ public: public: /// Return the MCSymbol corresponding to the assembler temporary label with /// the specified stem and unique ID. - MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; + MCSymbol *GetTempSymbol(const Twine &Name, unsigned ID) const; /// Return an assembler temporary label with the specified stem. - MCSymbol *GetTempSymbol(Twine Name) const; + MCSymbol *GetTempSymbol(const Twine &Name) const; /// Return the MCSymbol for a private symbol with global value name as its /// base, with the specified suffix. @@ -397,7 +424,7 @@ public: const MCSymbol *SectionLabel) const; /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. - virtual unsigned getISAEncoding() { return 0; } + virtual unsigned getISAEncoding(const Function *) { return 0; } /// Emit a dwarf register operation for describing /// - a small value occupying only part of a register or @@ -423,9 +450,8 @@ public: unsigned PieceOffset = 0) const; /// EmitDwarfRegOp - Emit a dwarf register operation. - /// \param Indirect whether this is a register-indirect address - virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, - bool Indirect) const; + virtual void EmitDwarfRegOp(ByteStreamer &BS, + const MachineLocation &MLoc) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -465,6 +491,10 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS); + /// Let the target do anything it needs to do before emitting inlineasm. + /// \p StartInfo - the subtarget info before parsing inline asm + virtual void emitInlineAsmStart() const; + /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the /// inlineasm contains directives to switch modes. diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h new file mode 100644 index 0000000..ff85b06 --- /dev/null +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -0,0 +1,723 @@ +//===- BasicTTIImpl.h -------------------------------------------*- 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 helper that implements much of the TTI interface in +/// terms of the target-independent code generator and TargetLowering +/// interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BASICTTIIMPL_H +#define LLVM_CODEGEN_BASICTTIIMPL_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetTransformInfoImpl.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +namespace llvm { + +extern cl::opt PartialUnrollingThreshold; + +/// \brief Base class which can be used to help build a TTI implementation. +/// +/// This class provides as much implementation of the TTI interface as is +/// possible using the target independent parts of the code generator. +/// +/// In order to subclass it, your class must implement a getST() method to +/// return the subtarget, and a getTLI() method to return the target lowering. +/// We need these methods implemented in the derived class so that this class +/// doesn't have to duplicate storage for them. +template +class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { +private: + typedef TargetTransformInfoImplCRTPBase BaseT; + typedef TargetTransformInfo TTI; + + /// Estimate the overhead of scalarizing an instruction. Insert and Extract + /// are set if the result needs to be inserted and/or extracted from vectors. + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) { + assert(Ty->isVectorTy() && "Can only scalarize vectors"); + unsigned Cost = 0; + + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + if (Insert) + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + if (Extract) + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + + return Cost; + } + + /// Estimate the cost overhead of SK_Alternate shuffle. + unsigned getAltShuffleOverhead(Type *Ty) { + assert(Ty->isVectorTy() && "Can only shuffle vectors"); + unsigned Cost = 0; + // Shuffle cost is equal to the cost of extracting element from its argument + // plus the cost of inserting them onto the result vector. + + // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from + // index 0 of first vector, index 1 of second vector,index 2 of first + // vector and finally index 3 of second vector and insert them at index + // <0,1,2,3> of result vector. + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + return Cost; + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetSubtargetInfo *getST() const { + return static_cast(this)->getST(); + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetLoweringBase *getTLI() const { + return static_cast(this)->getTLI(); + } + +protected: + explicit BasicTTIImplBase(const TargetMachine *TM) + : BaseT(TM->getDataLayout()) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImplBase(const BasicTTIImplBase &Arg) + : BaseT(static_cast(Arg)) {} + BasicTTIImplBase(BasicTTIImplBase &&Arg) + : BaseT(std::move(static_cast(Arg))) {} + BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { + BaseT::operator=(static_cast(RHS)); + return *this; + } + BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; + } + + /// \name Scalar TTI Implementations + /// @{ + + bool hasBranchDivergence() { return false; } + + bool isLegalAddImmediate(int64_t imm) { + return getTLI()->isLegalAddImmediate(imm); + } + + bool isLegalICmpImmediate(int64_t imm) { + return getTLI()->isLegalICmpImmediate(imm); + } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->isLegalAddressingMode(AM, Ty); + } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->getScalingFactorCost(AM, Ty); + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { + return getTLI()->isTruncateFree(Ty1, Ty2); + } + + bool isProfitableToHoist(Instruction *I) { + return getTLI()->isProfitableToHoist(I); + } + + bool isTypeLegal(Type *Ty) { + EVT VT = getTLI()->getValueType(Ty); + return getTLI()->isTypeLegal(VT); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) { + if (IID == Intrinsic::cttz) { + if (getTLI()->isCheapToSpeculateCttz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + if (IID == Intrinsic::ctlz) { + if (getTLI()->isCheapToSpeculateCtlz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); } + + unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); } + + bool shouldBuildLookupTables() { + const TargetLoweringBase *TLI = getTLI(); + return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other); + } + + bool haveFastSqrt(Type *Ty) { + const TargetLoweringBase *TLI = getTLI(); + EVT VT = TLI->getValueType(Ty); + return TLI->isTypeLegal(VT) && + TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); + } + + unsigned getFPOpCost(Type *Ty) { + // By default, FP instructions are no more expensive since they are + // implemented in HW. Target specific TTI can override this. + return TargetTransformInfo::TCC_Basic; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + const TargetLoweringBase *TLI = getTLI(); + switch (Opcode) { + default: break; + case Instruction::Trunc: { + if (TLI->isTruncateFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + case Instruction::ZExt: { + if (TLI->isZExtFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + } + + return BaseT::getOperationCost(Opcode, Ty, OpTy); + } + + void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) { + // This unrolling functionality is target independent, but to provide some + // motivation for its intended use, for x86: + + // According to the Intel 64 and IA-32 Architectures Optimization Reference + // Manual, Intel Core models and later have a loop stream detector (and + // associated uop queue) that can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have no more than 4 (8 for Nehalem and later) branches + // taken, and none of them may be calls. + // - The loop can have no more than 18 (28 for Nehalem and later) uops. + + // According to the Software Optimization Guide for AMD Family 15h + // Processors, models 30h-4fh (Steamroller and later) have a loop predictor + // and loop buffer which can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have fewer than 16 branches + // - The loop must have less than 40 uops in all executed loop branches + + // The number of taken branches in a loop is hard to estimate here, and + // benchmarking has revealed that it is better not to be conservative when + // estimating the branch count. As a result, we'll ignore the branch limits + // until someone finds a case where it matters in practice. + + unsigned MaxOps; + const TargetSubtargetInfo *ST = getST(); + if (PartialUnrollingThreshold.getNumOccurrences() > 0) + MaxOps = PartialUnrollingThreshold; + else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) + MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; + else + return; + + // Scan the loop: don't unroll loops with calls. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E; + ++I) { + BasicBlock *BB = *I; + + for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J) + if (isa(J) || isa(J)) { + ImmutableCallSite CS(J); + if (const Function *F = CS.getCalledFunction()) { + if (!static_cast(this)->isLoweredToCall(F)) + continue; + } + + return; + } + } + + // Enable runtime and partial unrolling up to the specified size. + UP.Partial = UP.Runtime = true; + UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps; + } + + /// @} + + /// \name Vector TTI Implementations + /// @{ + + unsigned getNumberOfRegisters(bool Vector) { return 1; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor() { return 1; } + + unsigned getArithmeticInstrCost( + unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, + TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, + TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) { + // Check if any of the operands are vector operands. + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair LT = TLI->getTypeLegalizationCost(Ty); + + bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); + // Assume that floating point arithmetic operations cost twice as much as + // integer operations. + unsigned OpCost = (IsFloat ? 2 : 1); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2 * OpCost; + return LT.first * 1 * OpCost; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2 * OpCost; + } + + // Else, assume that we need to scalarize this op. + if (Ty->isVectorTy()) { + unsigned Num = Ty->getVectorNumElements(); + unsigned Cost = static_cast(this) + ->getArithmeticInstrCost(Opcode, Ty->getScalarType()); + // return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(Ty, true, true) + Num * Cost; + } + + // We don't know anything about this scalar instruction. + return OpCost; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) { + if (Kind == TTI::SK_Alternate) { + return getAltShuffleOverhead(Tp); + } + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair SrcLT = TLI->getTypeLegalizationCost(Src); + std::pair DstLT = TLI->getTypeLegalizationCost(Dst); + + // Check for NOOP conversions. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Bitcast between types that are legalized to the same type are free. + if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc) + return 0; + } + + if (Opcode == Instruction::Trunc && + TLI->isTruncateFree(SrcLT.second, DstLT.second)) + return 0; + + if (Opcode == Instruction::ZExt && + TLI->isZExtFree(SrcLT.second, DstLT.second)) + return 0; + + // If the cast is marked as legal (or promote) then assume low cost. + if (SrcLT.first == DstLT.first && + TLI->isOperationLegalOrPromote(ISD, DstLT.second)) + return 1; + + // Handle scalar conversions. + if (!Src->isVectorTy() && !Dst->isVectorTy()) { + + // Scalar bitcasts are usually free. + if (Opcode == Instruction::BitCast) + return 0; + + // Just check the op cost. If the operation is legal then assume it costs + // 1. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return 1; + + // Assume that illegal scalar instruction are expensive. + return 4; + } + + // Check vector-to-vector casts. + if (Dst->isVectorTy() && Src->isVectorTy()) { + + // If the cast is between same-sized registers, then the check is simple. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Assume that Zext is done using AND. + if (Opcode == Instruction::ZExt) + return 1; + + // Assume that sext is done using SHL and SRA. + if (Opcode == Instruction::SExt) + return 2; + + // Just check the op cost. If the operation is legal then assume it + // costs + // 1 and multiply by the type-legalization overhead. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return SrcLT.first * 1; + } + + // If we are converting vectors and the operation is illegal, or + // if the vectors are legalized to different types, estimate the + // scalarization costs. + unsigned Num = Dst->getVectorNumElements(); + unsigned Cost = static_cast(this)->getCastInstrCost( + Opcode, Dst->getScalarType(), Src->getScalarType()); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting and extracting the values. + return getScalarizationOverhead(Dst, true, true) + Num * Cost; + } + + // We already handled vector-to-vector and scalar-to-scalar conversions. + // This + // is where we handle bitcast between vectors and scalars. We need to assume + // that the conversion is scalarized in one way or another. + if (Opcode == Instruction::BitCast) + // Illegal bitcasts are done by storing and loading from a stack slot. + return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true) + : 0) + + (Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false) + : 0); + + llvm_unreachable("Unhandled cast"); + } + + unsigned getCFInstrCost(unsigned Opcode) { + // Branches are assumed to be predicted. + return 0; + } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + // Selects on vectors are actually vector selects. + if (ISD == ISD::SELECT) { + assert(CondTy && "CondTy must exist"); + if (CondTy->isVectorTy()) + ISD = ISD::VSELECT; + } + + std::pair LT = TLI->getTypeLegalizationCost(ValTy); + + if (!(ValTy->isVectorTy() && !LT.second.isVector()) && + !TLI->isOperationExpand(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. Multiply + // by the type-legalization overhead. + return LT.first * 1; + } + + // Otherwise, assume that the cast is scalarized. + if (ValTy->isVectorTy()) { + unsigned Num = ValTy->getVectorNumElements(); + if (CondTy) + CondTy = CondTy->getScalarType(); + unsigned Cost = static_cast(this)->getCmpSelInstrCost( + Opcode, ValTy->getScalarType(), CondTy); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(ValTy, true, false) + Num * Cost; + } + + // Unknown scalar opcode. + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + std::pair LT = + getTLI()->getTypeLegalizationCost(Val->getScalarType()); + + return LT.first; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + assert(!Src->isVoidTy() && "Invalid type"); + std::pair LT = getTLI()->getTypeLegalizationCost(Src); + + // Assuming that all loads of legal types cost 1. + unsigned Cost = LT.first; + + if (Src->isVectorTy() && + Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { + // This is a vector load that legalizes to a larger type than the vector + // itself. Unless the corresponding extending load or truncating store is + // legal, then this will scalarize. + TargetLowering::LegalizeAction LA = TargetLowering::Expand; + EVT MemVT = getTLI()->getValueType(Src, true); + if (MemVT.isSimple() && MemVT != MVT::Other) { + if (Opcode == Instruction::Store) + LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); + else + LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT); + } + + if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { + // This is a vector load/store for some illegal type that is scalarized. + // We must account for the cost of building or decomposing the vector. + Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store, + Opcode == Instruction::Store); + } + } + + return Cost; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Tys) { + unsigned ISD = 0; + switch (IID) { + default: { + // Assume that we need to scalarize this intrinsic. + unsigned ScalarizationCost = 0; + unsigned ScalarCalls = 1; + if (RetTy->isVectorTy()) { + ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + if (Tys[i]->isVectorTy()) { + ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + } + + return ScalarCalls + ScalarizationCost; + } + // Look for intrinsics that can be lowered directly or turned into a scalar + // intrinsic call. + case Intrinsic::sqrt: + ISD = ISD::FSQRT; + break; + case Intrinsic::sin: + ISD = ISD::FSIN; + break; + case Intrinsic::cos: + ISD = ISD::FCOS; + break; + case Intrinsic::exp: + ISD = ISD::FEXP; + break; + case Intrinsic::exp2: + ISD = ISD::FEXP2; + break; + case Intrinsic::log: + ISD = ISD::FLOG; + break; + case Intrinsic::log10: + ISD = ISD::FLOG10; + break; + case Intrinsic::log2: + ISD = ISD::FLOG2; + break; + case Intrinsic::fabs: + ISD = ISD::FABS; + break; + case Intrinsic::minnum: + ISD = ISD::FMINNUM; + break; + case Intrinsic::maxnum: + ISD = ISD::FMAXNUM; + break; + case Intrinsic::copysign: + ISD = ISD::FCOPYSIGN; + break; + case Intrinsic::floor: + ISD = ISD::FFLOOR; + break; + case Intrinsic::ceil: + ISD = ISD::FCEIL; + break; + case Intrinsic::trunc: + ISD = ISD::FTRUNC; + break; + case Intrinsic::nearbyint: + ISD = ISD::FNEARBYINT; + break; + case Intrinsic::rint: + ISD = ISD::FRINT; + break; + case Intrinsic::round: + ISD = ISD::FROUND; + break; + case Intrinsic::pow: + ISD = ISD::FPOW; + break; + case Intrinsic::fma: + ISD = ISD::FMA; + break; + case Intrinsic::fmuladd: + ISD = ISD::FMA; + break; + // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free. + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return 0; + case Intrinsic::masked_store: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + case Intrinsic::masked_load: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + } + + const TargetLoweringBase *TLI = getTLI(); + std::pair LT = TLI->getTypeLegalizationCost(RetTy); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2; + return LT.first * 1; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2; + } + + // If we can't lower fmuladd into an FMA estimate the cost as a floating + // point mul followed by an add. + if (IID == Intrinsic::fmuladd) + return static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + + // Else, assume that we need to scalarize this intrinsic. For math builtins + // this will emit a costly libcall, adding call overhead and spills. Make it + // very expensive. + if (RetTy->isVectorTy()) { + unsigned Num = RetTy->getVectorNumElements(); + unsigned Cost = static_cast(this)->getIntrinsicInstrCost( + IID, RetTy->getScalarType(), Tys); + return 10 * Cost * Num; + } + + // This is going to be turned into a library call, make it expensive. + return 10; + } + + unsigned getNumberOfParts(Type *Tp) { + std::pair LT = getTLI()->getTypeLegalizationCost(Tp); + return LT.first; + } + + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; } + + unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) { + assert(Ty->isVectorTy() && "Expect a vector type"); + unsigned NumVecElts = Ty->getVectorNumElements(); + unsigned NumReduxLevels = Log2_32(NumVecElts); + unsigned ArithCost = + NumReduxLevels * + static_cast(this)->getArithmeticInstrCost(Opcode, Ty); + // Assume the pairwise shuffles add a cost. + unsigned ShuffleCost = + NumReduxLevels * (IsPairwise + 1) * + static_cast(this) + ->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty); + return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true); + } + + /// @} +}; + +/// \brief Concrete BasicTTIImpl that can be used if no further customization +/// is needed. +class BasicTTIImpl : public BasicTTIImplBase { + typedef BasicTTIImplBase BaseT; + friend class BasicTTIImplBase; + + const TargetSubtargetInfo *ST; + const TargetLoweringBase *TLI; + + const TargetSubtargetInfo *getST() const { return ST; } + const TargetLoweringBase *getTLI() const { return TLI; } + +public: + explicit BasicTTIImpl(const TargetMachine *ST, Function &F); + + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImpl(const BasicTTIImpl &Arg) + : BaseT(static_cast(Arg)), ST(Arg.ST), TLI(Arg.TLI) {} + BasicTTIImpl(BasicTTIImpl &&Arg) + : BaseT(std::move(static_cast(Arg))), ST(std::move(Arg.ST)), + TLI(std::move(Arg.TLI)) {} + BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { + BaseT::operator=(static_cast(RHS)); + ST = RHS.ST; + TLI = RHS.TLI; + return *this; + } + BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + ST = std::move(RHS.ST); + TLI = std::move(RHS.TLI); + return *this; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 0b2ccc6..e2b744f 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -122,8 +122,8 @@ public: // There is no need to differentiate between a pending CCValAssign and other // kinds, as they are stored in a different list. static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, - LocInfo HTP) { - return getReg(ValNo, ValVT, 0, LocVT, HTP); + LocInfo HTP, unsigned ExtraInfo = 0) { + return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); } void convertToReg(unsigned RegNo) { @@ -146,6 +146,7 @@ public: unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } @@ -158,6 +159,16 @@ public: } }; +/// Describes a register that needs to be forwarded from the prologue to a +/// musttail call. +struct ForwardedRegister { + ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT) + : VReg(VReg), PReg(PReg), VT(VT) {} + unsigned VReg; + MCPhysReg PReg; + MVT VT; +}; + /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. It returns 'true' if it failed to handle Val. typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, @@ -302,13 +313,13 @@ public: /// produce a single value. void AnalyzeCallResult(MVT VT, CCAssignFn Fn); - /// getFirstUnallocated - Return the first unallocated register in the set, or - /// NumRegs if they are all allocated. - unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const { - for (unsigned i = 0; i != NumRegs; ++i) + /// getFirstUnallocated - Return the index of the first unallocated register + /// in the set, or Regs.size() if they are all allocated. + unsigned getFirstUnallocated(ArrayRef Regs) const { + for (unsigned i = 0; i < Regs.size(); ++i) if (!isAllocated(Regs[i])) return i; - return NumRegs; + return Regs.size(); } /// AllocateReg - Attempt to allocate one register. If it is not available, @@ -331,9 +342,9 @@ public: /// AllocateReg - Attempt to allocate one of the specified registers. If none /// are available, return zero. Otherwise, return the first one available, /// marking it and any aliases as allocated. - unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -345,8 +356,12 @@ public: /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive /// registers. If this is not possible, return zero. Otherwise, return the first /// register of the block that were allocated, marking the entire block as allocated. - unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) { - for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) { + unsigned AllocateRegBlock(ArrayRef Regs, unsigned RegsRequired) { + if (RegsRequired > Regs.size()) + return 0; + + for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; + ++StartIdx) { bool BlockAvailable = true; // Check for already-allocated regs in this block for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { @@ -368,10 +383,9 @@ public: } /// Version of AllocateReg with list of registers to be shadowed. - unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs, - unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs, const MCPhysReg *ShadowRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -401,8 +415,8 @@ public: /// Version of AllocateStack with list of extra registers to be shadowed. /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. unsigned AllocateStack(unsigned Size, unsigned Align, - const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) { - for (unsigned i = 0; i < NumShadowRegs; ++i) + ArrayRef ShadowRegs) { + for (unsigned i = 0; i < ShadowRegs.size(); ++i) MarkAllocated(ShadowRegs[i]); return AllocateStack(Size, Align); } @@ -466,6 +480,19 @@ public: return PendingLocs; } + /// Compute the remaining unused register parameters that would be used for + /// the given value type. This is useful when varargs are passed in the + /// registers that normal prototyped parameters would be passed in, or for + /// implementing perfect forwarding. + void getRemainingRegParmsForType(SmallVectorImpl &Regs, MVT VT, + CCAssignFn Fn); + + /// Compute the set of registers that need to be preserved and forwarded to + /// any musttail calls. + void analyzeMustTailForwardedRegisters( + SmallVectorImpl &Forwards, ArrayRef RegParmTypes, + CCAssignFn Fn); + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 973c595..9f86429 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -207,6 +207,10 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt UniqueSectionNames("unique-section-names", + cl::desc("Give unique names to every section"), + cl::init(true)); + cl::opt JTableType("jump-table-type", cl::desc("Choose the type of Jump-Instruction Table for jumptable."), @@ -284,6 +288,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h new file mode 100644 index 0000000..e310aef --- /dev/null +++ b/include/llvm/CodeGen/DIE.h @@ -0,0 +1,587 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; + + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; + + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; + +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + // This can't be a vector because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector> Children; + + DIE *Parent; + + /// Attribute values. + /// + SmallVector Values; + +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + +public: + explicit DIE(dwarf::Tag Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector> &getChildren() const { + return Children; + } + const SmallVectorImpl &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(std::unique_ptr Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Child->Parent = this; + Children.push_back(std::move(Child)); + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, + }; + +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + +#ifndef NDEBUG + virtual void print(raw_ostream &O) const = 0; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; + +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} + + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; + +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + StringRef Str; + +public: + DIEString(const DIEValue *Acc, StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} + + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE &Entry; + +public: + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { + } + + DIE &getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index b5405f9..1dca2ce 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -18,9 +18,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { @@ -76,6 +76,8 @@ public: unsigned ResultReg; unsigned NumResultRegs; + bool IsPatchPoint; + SmallVector OutVals; SmallVector OutFlags; SmallVector OutRegs; @@ -87,7 +89,7 @@ public: IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0) {} + ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -162,6 +164,11 @@ public: return *this; } + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; + } + ArgListTy &getArgs() { return Args; } void clearOuts() { diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h index a6232c5..ec8e2ef 100644 --- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h +++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h @@ -18,7 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Pass.h" #include "llvm/Target/TargetOptions.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 91f20d0..e12866e 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -20,8 +20,8 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -88,6 +88,12 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap RegFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) + /// used to spill values at a statepoint. We store them here to enable + /// reuse of the same stack slots across different statepoints in different + /// basic blocks. + SmallVector StatepointStackSlots; + /// MBB - The current block. MachineBasicBlock *MBB; @@ -200,6 +206,9 @@ public: return; unsigned Reg = It->second; + if (Reg == 0) + return; + LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } @@ -223,11 +232,6 @@ private: /// floating-point support. void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI); -/// AddCatchInfo - Extract the personality and type infos from an eh.selector -/// call, and add them to the specified machine basic block. -void AddCatchInfo(const CallInst &I, - MachineModuleInfo *MMI, MachineBasicBlock *MBB); - /// AddLandingPadInfo - Extract the exception handling information from the /// landingpad instruction and add them to the specified machine module info. void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index ddcc823..357b2d8 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -34,168 +34,173 @@ #define LLVM_CODEGEN_GCMETADATA_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/GCStrategy.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" - #include namespace llvm { - class AsmPrinter; - class GCStrategy; - class Constant; - class MCSymbol; - - namespace GC { - /// PointKind - The type of a collector-safe point. - /// - enum PointKind { - Loop, ///< Instr is a loop (backwards branch). - Return, ///< Instr is a return instruction. - PreCall, ///< Instr is a call instruction. - PostCall ///< Instr is the return address of a call. - }; - } - - /// GCPoint - Metadata for a collector-safe point in machine code. +class AsmPrinter; +class Constant; +class MCSymbol; + +/// GCPoint - Metadata for a collector-safe point in machine code. +/// +struct GCPoint { + GC::PointKind Kind; ///< The kind of the safe point. + MCSymbol *Label; ///< A label. + DebugLoc Loc; + + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} +}; + +/// GCRoot - Metadata for a pointer to an object managed by the garbage +/// collector. +struct GCRoot { + int Num; ///< Usually a frame index. + int StackOffset; ///< Offset from the stack pointer. + const Constant *Metadata; ///< Metadata straight from the call + ///< to llvm.gcroot. + + GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} +}; + +/// Garbage collection metadata for a single function. Currently, this +/// information only applies to GCStrategies which use GCRoot. +class GCFunctionInfo { +public: + typedef std::vector::iterator iterator; + typedef std::vector::iterator roots_iterator; + typedef std::vector::const_iterator live_iterator; + +private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector Roots; + std::vector SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + +public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. /// - struct GCPoint { - GC::PointKind Kind; ///< The kind of the safe point. - MCSymbol *Label; ///< A label. - DebugLoc Loc; - - GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) - : Kind(K), Label(L), Loc(DL) {} - }; - - /// GCRoot - Metadata for a pointer to an object managed by the garbage - /// collector. - struct GCRoot { - int Num; ///< Usually a frame index. - int StackOffset; ///< Offset from the stack pointer. - const Constant *Metadata; ///< Metadata straight from the call - ///< to llvm.gcroot. + const Function &getFunction() const { return F; } - GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} - }; - - - /// GCFunctionInfo - Garbage collection metadata for a single function. + /// getStrategy - Return the GC strategy for the function. /// - class GCFunctionInfo { - public: - typedef std::vector::iterator iterator; - typedef std::vector::iterator roots_iterator; - typedef std::vector::const_iterator live_iterator; - - private: - const Function &F; - GCStrategy &S; - uint64_t FrameSize; - std::vector Roots; - std::vector SafePoints; - - // FIXME: Liveness. A 2D BitVector, perhaps? - // - // BitVector Liveness; - // - // bool islive(int point, int root) = - // Liveness[point * SafePoints.size() + root] - // - // The bit vector is the more compact representation where >3.2% of roots - // are live per safe point (1.5% on 64-bit hosts). - - public: - GCFunctionInfo(const Function &F, GCStrategy &S); - ~GCFunctionInfo(); - - /// getFunction - Return the function to which this metadata applies. - /// - const Function &getFunction() const { return F; } - - /// getStrategy - Return the GC strategy for the function. - /// - GCStrategy &getStrategy() { return S; } - - /// addStackRoot - Registers a root that lives on the stack. Num is the - /// stack object ID for the alloca (if the code generator is - // using MachineFrameInfo). - void addStackRoot(int Num, const Constant *Metadata) { - Roots.push_back(GCRoot(Num, Metadata)); - } - - /// removeStackRoot - Removes a root. - roots_iterator removeStackRoot(roots_iterator position) { - return Roots.erase(position); - } - - /// addSafePoint - Notes the existence of a safe point. Num is the ID of the - /// label just prior to the safe point (if the code generator is using - /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { - SafePoints.push_back(GCPoint(Kind, Label, DL)); - } - - /// getFrameSize/setFrameSize - Records the function's frame size. - /// - uint64_t getFrameSize() const { return FrameSize; } - void setFrameSize(uint64_t S) { FrameSize = S; } - - /// begin/end - Iterators for safe points. - /// - iterator begin() { return SafePoints.begin(); } - iterator end() { return SafePoints.end(); } - size_t size() const { return SafePoints.size(); } - - /// roots_begin/roots_end - Iterators for all roots in the function. - /// - roots_iterator roots_begin() { return Roots.begin(); } - roots_iterator roots_end () { return Roots.end(); } - size_t roots_size() const { return Roots.size(); } - - /// live_begin/live_end - Iterators for live roots at a given safe point. - /// - live_iterator live_begin(const iterator &p) { return roots_begin(); } - live_iterator live_end (const iterator &p) { return roots_end(); } - size_t live_size(const iterator &p) const { return roots_size(); } - }; - - - /// GCModuleInfo - Garbage collection metadata for a whole module. - /// - class GCModuleInfo : public ImmutablePass { - typedef StringMap strategy_map_type; - typedef std::vector> list_type; - typedef DenseMap finfo_map_type; - - strategy_map_type StrategyMap; - list_type StrategyList; - finfo_map_type FInfoMap; + GCStrategy &getStrategy() { return S; } - GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, const Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } - public: - typedef list_type::const_iterator iterator; + /// removeStackRoot - Removes a root. + roots_iterator removeStackRoot(roots_iterator position) { + return Roots.erase(position); + } - static char ID; + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); + } - GCModuleInfo(); + /// getFrameSize/setFrameSize - Records the function's frame size. + /// + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } - /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should - /// call it in doFinalization(). - /// - void clear(); + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } - /// begin/end - Iterators for used strategies. - /// - iterator begin() const { return StrategyList.begin(); } - iterator end() const { return StrategyList.end(); } + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end() { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } - /// get - Look up function metadata. - /// - GCFunctionInfo &getFunctionInfo(const Function &F); - }; + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end(const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } +}; + +/// An analysis pass which caches information about the entire Module. +/// Records both the function level information used by GCRoots and a +/// cache of the 'active' gc strategy objects for the current Module. +class GCModuleInfo : public ImmutablePass { + /// An owning list of all GCStrategies which have been created + SmallVector, 1> GCStrategyList; + /// A helper map to speedup lookups into the above list + StringMap GCStrategyMap; + +public: + /// Lookup the GCStrategy object associated with the given gc name. + /// Objects are owned internally; No caller should attempt to delete the + /// returned objects. + GCStrategy *getGCStrategy(const StringRef Name); + + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + +private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap finfo_map_type; + finfo_map_type FInfoMap; + +public: + typedef SmallVector,1>::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + + /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should + /// call it in doFinalization(). + /// + void clear(); + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return GCStrategyList.begin(); } + iterator end() const { return GCStrategyList.end(); } + + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. + GCFunctionInfo &getFunctionInfo(const Function &F); +}; } #endif diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 4a6b5ac..2208470 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -26,49 +26,39 @@ namespace llvm { - class GCMetadataPrinter; - - /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the - /// defaults from Registry. - typedef Registry GCMetadataPrinterRegistry; - - /// GCMetadataPrinter - Emits GC metadata as assembly code. - /// - class GCMetadataPrinter { - public: - typedef GCStrategy::list_type list_type; - typedef GCStrategy::iterator iterator; - - private: - GCStrategy *S; - - friend class AsmPrinter; - - protected: - // May only be subclassed. - GCMetadataPrinter(); - - private: - GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - GCMetadataPrinter & - operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - - public: - GCStrategy &getStrategy() { return *S; } - const Module &getModule() const { return S->getModule(); } - - /// begin/end - Iterate over the collected function metadata. - iterator begin() { return S->begin(); } - iterator end() { return S->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(AsmPrinter &AP); - - virtual void finishAssembly(AsmPrinter &AP); - - virtual ~GCMetadataPrinter(); - }; - +class GCMetadataPrinter; + +/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the +/// defaults from Registry. +typedef Registry GCMetadataPrinterRegistry; + +/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are +/// created, managed, and owned by the AsmPrinter. +class GCMetadataPrinter { +private: + GCStrategy *S; + friend class AsmPrinter; + +protected: + // May only be subclassed. + GCMetadataPrinter(); + +private: + GCMetadataPrinter(const GCMetadataPrinter &) = delete; + GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete; + +public: + GCStrategy &getStrategy() { return *S; } + + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + + virtual ~GCMetadataPrinter(); +}; } #endif diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 81e1f85..869f888 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -12,10 +12,15 @@ // specified in a function's 'gc' attribute. Algorithms are enabled by setting // flags in a subclass's constructor, and some virtual methods can be // overridden. -// -// When requested, the GCStrategy will be populated with data about each -// function which uses it. Specifically: -// +// +// GCStrategy is relevant for implementations using either gc.root or +// gc.statepoint based lowering strategies, but is currently focused mostly on +// options for gc.root. This will change over time. +// +// When requested by a subclass of GCStrategy, the gc.root implementation will +// populate GCModuleInfo and GCFunctionInfo with that about each Function in +// the Module that opts in to garbage collection. Specifically: +// // - Safe points // Garbage collection is generally only possible at certain points in code. // GCStrategy can request that the collector insert such points: @@ -23,7 +28,7 @@ // - At and after any call to a subroutine // - Before returning from the current function // - Before backwards branches (loops) -// +// // - Roots // When a reference to a GC-allocated object exists on the stack, it must be // stored in an alloca registered with llvm.gcoot. @@ -31,123 +36,142 @@ // This information can used to emit the metadata tables which are required by // the target garbage collector runtime. // +// When used with gc.statepoint, information about safepoint and roots can be +// found in the binary StackMap section after code generation. Safepoint +// placement is currently the responsibility of the frontend, though late +// insertion support is planned. gc.statepoint does not currently support +// custom stack map formats; such can be generated by parsing the standard +// stack map section if desired. +// +// The read and write barrier support can be used with either implementation. +// //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GCSTRATEGY_H -#define LLVM_CODEGEN_GCSTRATEGY_H +#ifndef LLVM_IR_GCSTRATEGY_H +#define LLVM_IR_GCSTRATEGY_H -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ADT/Optional.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Registry.h" #include namespace llvm { - - class GCStrategy; - - /// The GC strategy registry uses all the defaults from Registry. - /// - typedef Registry GCRegistry; - - /// GCStrategy describes a garbage collector algorithm's code generation - /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. - class GCStrategy { - public: - typedef std::vector> list_type; - typedef list_type::iterator iterator; - - private: - friend class GCModuleInfo; - const Module *M; - std::string Name; - - list_type Functions; - - protected: - unsigned NeededSafePoints; ///< Bitmask of required safe points. - bool CustomReadBarriers; ///< Default is to insert loads. - bool CustomWriteBarriers; ///< Default is to insert stores. - bool CustomRoots; ///< Default is to pass through to backend. - bool CustomSafePoints; ///< Default is to use NeededSafePoints - ///< to find safe points. - bool InitRoots; ///< If set, roots are nulled during lowering. - bool UsesMetadata; ///< If set, backend must emit metadata tables. - - public: - GCStrategy(); - - virtual ~GCStrategy() {} - - - /// getName - The name of the GC strategy, for debugging. - /// - const std::string &getName() const { return Name; } - - /// getModule - The module within which the GC strategy is operating. - /// - const Module &getModule() const { return *M; } - - /// needsSafePoitns - True if safe points of any kind are required. By - // default, none are recorded. - bool needsSafePoints() const { - return CustomSafePoints || NeededSafePoints != 0; - } - - /// needsSafePoint(Kind) - True if the given kind of safe point is - // required. By default, none are recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// customWriteBarrier - By default, write barriers are replaced with simple - /// store instructions. If true, then - /// performCustomLowering must instead lower them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// customReadBarrier - By default, read barriers are replaced with simple - /// load instructions. If true, then - /// performCustomLowering must instead lower them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// customRoots - By default, roots are left for the code generator so it - /// can generate a stack map. If true, then - // performCustomLowering must delete them. - bool customRoots() const { return CustomRoots; } - - /// customSafePoints - By default, the GC analysis will find safe - /// points according to NeededSafePoints. If true, - /// then findCustomSafePoints must create them. - bool customSafePoints() const { return CustomSafePoints; } - - /// initializeRoots - If set, gcroot intrinsics should initialize their - // allocas to null before the first use. This is - // necessary for most GCs and is enabled by default. - bool initializeRoots() const { return InitRoots; } - - /// usesMetadata - If set, appropriate metadata tables must be emitted by - /// the back-end (assembler, JIT, or otherwise). - bool usesMetadata() const { return UsesMetadata; } - - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insertFunctionMetadata - Creates metadata for a function. - /// - GCFunctionInfo *insertFunctionInfo(const Function &F); - - /// initializeCustomLowering/performCustomLowering - If any of the actions - /// are set to custom, performCustomLowering must be overriden to transform - /// the corresponding actions to LLVM IR. initializeCustomLowering is - /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. - virtual bool initializeCustomLowering(Module &F); - virtual bool performCustomLowering(Function &F); - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF); - }; - +namespace GC { +/// PointKind - The type of a collector-safe point. +/// +enum PointKind { + Loop, ///< Instr is a loop (backwards branch). + Return, ///< Instr is a return instruction. + PreCall, ///< Instr is a call instruction. + PostCall ///< Instr is the return address of a call. +}; +} + +/// GCStrategy describes a garbage collector algorithm's code generation +/// requirements, and provides overridable hooks for those needs which cannot +/// be abstractly described. GCStrategy objects must be looked up through +/// the Function. The objects themselves are owned by the Context and must +/// be immutable. +class GCStrategy { +private: + std::string Name; + friend class GCModuleInfo; + +protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + + unsigned NeededSafePoints; ///< Bitmask of required safe points. + bool CustomReadBarriers; ///< Default is to insert loads. + bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomRoots; ///< Default is to pass through to backend. + bool InitRoots; ///< If set, roots are nulled during lowering. + bool UsesMetadata; ///< If set, backend must emit metadata tables. + +public: + GCStrategy(); + virtual ~GCStrategy() {} + + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. + const std::string &getName() const { return Name; } + + /// By default, write barriers are replaced with simple store + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcwrite. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcread. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ + + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// True if the given kind of safe point is required. By default, none are + /// recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, you must provide a custom pass to lower + /// calls to @llvm.gcroot. + bool customRoots() const { return CustomRoots; } + + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. + bool initializeRoots() const { return InitRoots; } + + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. + bool usesMetadata() const { return UsesMetadata; } + + ///@} +}; + +/// Subclasses of GCStrategy are made available for use during compilation by +/// adding them to the global GCRegistry. This can done either within the +/// LLVM source tree or via a loadable plugin. An example registeration +/// would be: +/// static GCRegistry::Add X("custom-name", +/// "my custom supper fancy gc strategy"); +/// +/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also +/// register your GCMetadataPrinter subclass with the +/// GCMetadataPrinterRegistery as well. +typedef Registry GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index bb170c8..5bae41e 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -15,27 +15,29 @@ #define LLVM_CODEGEN_GCS_H namespace llvm { - class GCStrategy; - class GCMetadataPrinter; +class GCStrategy; +class GCMetadataPrinter; - /// FIXME: Collector instances are not useful on their own. These no longer - /// serve any purpose except to link in the plugins. +/// FIXME: Collector instances are not useful on their own. These no longer +/// serve any purpose except to link in the plugins. - /// Creates an ocaml-compatible garbage collector. - void linkOcamlGC(); +/// Creates an ocaml-compatible garbage collector. +void linkOcamlGC(); - /// Creates an ocaml-compatible metadata printer. - void linkOcamlGCPrinter(); +/// Creates an ocaml-compatible metadata printer. +void linkOcamlGCPrinter(); - /// Creates an erlang-compatible garbage collector. - void linkErlangGC(); +/// Creates an erlang-compatible garbage collector. +void linkErlangGC(); - /// Creates an erlang-compatible metadata printer. - void linkErlangGCPrinter(); +/// Creates an erlang-compatible metadata printer. +void linkErlangGCPrinter(); - /// Creates a shadow stack garbage collector. This collector requires no code - /// generator support. - void linkShadowStackGC(); +/// Creates a shadow stack garbage collector. This collector requires no code +/// generator support. +void linkShadowStackGC(); + +void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index bbf0ad3..8a31f7e 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover + /// intrinsic. Materializes the offset from the frame pointer of another + /// function to the result of llvm.frameallocate. + FRAME_ALLOC_RECOVER, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. READ_REGISTER, @@ -224,7 +229,14 @@ namespace ISD { SMULO, UMULO, /// Simple binary floating point operators. - FADD, FSUB, FMUL, FMA, FDIV, FREM, + FADD, FSUB, FMUL, FDIV, FREM, + + /// FMA - Perform a * b + c with no intermediate rounding step. + FMA, + + /// FMAD - Perform a * b + c, while getting the same result as the + /// separately rounded operations. + FMAD, /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This /// DAG node does not require that X and Y have the same type, just that the @@ -675,6 +687,11 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + // Masked load and store + MLOAD, MSTORE, + // Masked gather and scatter + MGATHER, MSCATTER, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, @@ -688,7 +705,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+180; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed @@ -745,7 +762,7 @@ namespace ISD { LAST_LOADEXT_TYPE }; - NodeType getExtForLoadExtType(LoadExtType); + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 021fd98..b3a8405 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -19,14 +19,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" -#include #include +#include namespace llvm { class MachineInstr; @@ -48,6 +48,8 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + assert((!D || D->isResolved()) && "Expected resolved node"); + assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); } @@ -116,8 +118,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - AssertingVH Desc; // Debug info descriptor. - AssertingVH InlinedAtLocation; // Location at which this + const MDNode *Desc; // Debug info descriptor. + const MDNode *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector Children; // Scopes defined in scope. @@ -178,9 +180,11 @@ public: return I != AbstractScopeMap.end() ? &I->second : nullptr; } - /// findInlinedScope - Find an inlined scope for the given DebugLoc or return - /// NULL. - LexicalScope *findInlinedScope(DebugLoc DL); + /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. + LexicalScope *findInlinedScope(const MDNode *N, const MDNode *IA) { + auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); + return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; + } /// findLexicalScope - Find regular lexical scope or return null. LexicalScope *findLexicalScope(const MDNode *N) { diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 372c294..e7ccbfa 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,6 +39,7 @@ namespace { llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); + llvm::linkStatepointExampleGC(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 6629e60..21634cb 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -27,6 +27,7 @@ #include "llvm/Support/Allocator.h" #include #include +#include namespace llvm { class CoalescerPair; @@ -119,6 +120,12 @@ namespace llvm { return isDeadDef() ? nullptr : LateVal; } + /// Returns the value alive at the end of the instruction, if any. This can + /// be a live-through value, a live def or a dead def. + VNInfo *valueOutOrDead() const { + return 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 { @@ -188,6 +195,12 @@ namespace llvm { Segments segments; // the liveness segments VNInfoList valnos; // value#'s + // The segment set is used temporarily to accelerate initial computation + // of live ranges of physical registers in computeRegUnitRange. + // After that the set is flushed to the segment vector and deleted. + typedef std::set SegmentSet; + SegmentSet *segmentSet; + typedef Segments::iterator iterator; iterator begin() { return segments.begin(); } iterator end() { return segments.end(); } @@ -204,6 +217,31 @@ namespace llvm { const_vni_iterator vni_begin() const { return valnos.begin(); } const_vni_iterator vni_end() const { return valnos.end(); } + /// Constructs a new LiveRange object. + LiveRange(bool UseSegmentSet = false) : segmentSet(nullptr) { + if (UseSegmentSet) + segmentSet = new SegmentSet(); + } + + /// Constructs a new LiveRange object by copying segments and valnos from + /// another LiveRange. + LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) + : segmentSet(nullptr) { + assert(Other.segmentSet == nullptr && + "Copying of LiveRanges with active SegmentSets is not supported"); + + // Duplicate valnos. + for (const VNInfo *VNI : Other.valnos) { + createValueCopy(VNI, Allocator); + } + // Now we can copy segments and remap their valnos. + for (const Segment &S : Other.segments) { + segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); + } + } + + ~LiveRange() { delete segmentSet; } + /// 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 range. If no Segment contains this position, but the @@ -217,6 +255,14 @@ namespace llvm { return I; } + const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + /// 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 ranges. @@ -397,17 +443,21 @@ namespace llvm { /// scanning the Other range starting at I. bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + /// Returns true if all segments of the @p Other live range are completely + /// covered by this live range. + /// Adjacent live ranges do not affect the covering:the liverange + /// [1,5](5,10] covers (3,7]. + bool covers(const LiveRange &Other) const; + /// 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()); - } + iterator addSegment(Segment S); - /// 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 segment before Kill, return NULL. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); + /// If this range is live before @p Use in the basic block that starts at + /// @p StartIdx, extend it to be live up to @p Use, and return the value. If + /// there is no segment before @p Use, return nullptr. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Use); /// join - Join two live ranges (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS ranges as specified. If @@ -435,6 +485,12 @@ namespace llvm { removeSegment(S.start, S.end, RemoveDeadValNo); } + /// Remove segment pointed to by iterator @p I from this range. This does + /// not remove dead value numbers. + iterator removeSegment(iterator I) { + return segments.erase(I); + } + /// Query Liveness at Idx. /// The sub-instruction slot of Idx doesn't matter, only the instruction /// it refers to is considered. @@ -484,9 +540,9 @@ namespace llvm { /// 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() < - i->end.getBaseIndex()) + for (const Segment &S : segments) + if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < + S.end.getBaseIndex()) return false; return true; } @@ -497,6 +553,12 @@ namespace llvm { return thisIndex < otherIndex; } + /// Flush segment set into the regular segment vector. + /// The method is to be called after the live range + /// has been created, if use of the segment set was + /// activated in the constructor of the live range. + void flushSegmentSet(); + void print(raw_ostream &OS) const; void dump() const; @@ -509,11 +571,13 @@ namespace llvm { void verify() const; #endif - private: + protected: + /// Append a segment to the list of segments. + void append(const LiveRange::Segment S); - iterator addSegmentFrom(Segment S, iterator From); - void extendSegmentEndTo(iterator I, SlotIndex NewEnd); - iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); + private: + friend class LiveRangeUpdater; + void addSegmentToSet(Segment S); void markValNoForDeletion(VNInfo *V); }; @@ -529,11 +593,124 @@ namespace llvm { public: typedef LiveRange super; + /// A live range for subregisters. The LaneMask specifies which parts of the + /// super register are covered by the interval. + /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). + class SubRange : public LiveRange { + public: + SubRange *Next; + unsigned LaneMask; + + /// Constructs a new SubRange object. + SubRange(unsigned LaneMask) + : Next(nullptr), LaneMask(LaneMask) { + } + + /// Constructs a new SubRange object by copying liveness from @p Other. + SubRange(unsigned LaneMask, const LiveRange &Other, + BumpPtrAllocator &Allocator) + : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) { + } + }; + + private: + SubRange *SubRanges; ///< Single linked list of subregister live ranges. + + public: 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) {} + : SubRanges(nullptr), reg(Reg), weight(Weight) {} + + ~LiveInterval() { + clearSubRanges(); + } + + template + class SingleLinkedListIterator { + T *P; + public: + SingleLinkedListIterator(T *P) : P(P) {} + SingleLinkedListIterator &operator++() { + P = P->Next; + return *this; + } + SingleLinkedListIterator &operator++(int) { + SingleLinkedListIterator res = *this; + ++*this; + return res; + } + bool operator!=(const SingleLinkedListIterator &Other) { + return P != Other.operator->(); + } + bool operator==(const SingleLinkedListIterator &Other) { + return P == Other.operator->(); + } + T &operator*() const { + return *P; + } + T *operator->() const { + return P; + } + }; + + typedef SingleLinkedListIterator subrange_iterator; + subrange_iterator subrange_begin() { + return subrange_iterator(SubRanges); + } + subrange_iterator subrange_end() { + return subrange_iterator(nullptr); + } + + typedef SingleLinkedListIterator const_subrange_iterator; + const_subrange_iterator subrange_begin() const { + return const_subrange_iterator(SubRanges); + } + const_subrange_iterator subrange_end() const { + return const_subrange_iterator(nullptr); + } + + iterator_range subranges() { + return make_range(subrange_begin(), subrange_end()); + } + + iterator_range subranges() const { + return make_range(subrange_begin(), subrange_end()); + } + + /// Creates a new empty subregister live range. The range is added at the + /// beginning of the subrange list; subrange iterators stay valid. + SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) { + SubRange *Range = new (Allocator) SubRange(LaneMask); + appendSubRange(Range); + return Range; + } + + /// Like createSubRange() but the new range is filled with a copy of the + /// liveness information in @p CopyFrom. + SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask, + const LiveRange &CopyFrom) { + SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); + appendSubRange(Range); + return Range; + } + + /// Returns true if subregister liveness information is available. + bool hasSubRanges() const { + return SubRanges != nullptr; + } + + /// Removes all subregister liveness information. + void clearSubRanges(); + + /// Removes all subranges without any segments (subranges without segments + /// are not considered valid and should only exist temporarily). + void removeEmptySubRanges(); + + /// Construct main live range by merging the SubRanges of @p LI. + void constructMainRangeFromSubranges(const SlotIndexes &Indexes, + VNInfo::Allocator &VNIAllocator); /// getSize - Returns the sum of sizes of all the LiveRange's. /// @@ -558,9 +735,26 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; + /// \brief Walks the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify(const MachineRegisterInfo *MRI = nullptr) const {} +#else + void verify(const MachineRegisterInfo *MRI = nullptr) const; +#endif + private: - LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; + LiveInterval& operator=(const LiveInterval& rhs) = delete; + + /// Appends @p Range to SubRanges list. + void appendSubRange(SubRange *Range) { + Range->Next = SubRanges; + SubRanges = Range; + } + /// Free memory held by SubRange. + void freeSubRange(SubRange *S); }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index f9bd317..dc52c0a 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -27,12 +27,15 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetRegisterInfo.h" #include #include namespace llvm { +extern cl::opt UseSegmentSetForPhysRegs; + class AliasAnalysis; class BitVector; class BlockFrequency; @@ -154,16 +157,11 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); - /// \brief Walk the values in the given interval and compute which ones - /// are dead. Dead values are not deleted, however: - /// - Dead PHIDef values are marked as unused. - /// - New dead machine instructions are added to the dead vector. - /// - CanSeparate is set to true if the interval may have been separated - /// into multiple connected components. - void computeDeadValues(LiveInterval *li, - LiveRange &LR, - bool *CanSeparate, - SmallVectorImpl *dead); + /// Specialized version of + /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) + /// that works on a subregister live range and only looks at uses matching + /// the lane mask of the subregister range. + void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -175,14 +173,15 @@ namespace llvm { /// See also LiveRangeCalc::extend(). 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 + + /// If @p LR has a live value at @p Kill, prune its live range by removing + /// any liveness reachable from Kill. Add live range end points to /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the /// value's live range. /// /// Calling pruneValue() and extendToIndices() can be used to reconstruct /// SSA form after adding defs to a virtual register. - void pruneValue(LiveInterval *LI, SlotIndex Kill, + void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl *EndPoints); SlotIndexes *getSlotIndexes() const { @@ -381,7 +380,8 @@ namespace llvm { LiveRange *LR = RegUnitRanges[Unit]; if (!LR) { // Compute missing ranges on demand. - RegUnitRanges[Unit] = LR = new LiveRange(); + // Use segment set to speed-up initial computation of the live range. + RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs); computeRegUnitRange(*LR, Unit); } return *LR; @@ -397,6 +397,15 @@ namespace llvm { return RegUnitRanges[Unit]; } + /// Remove value numbers and related live segments starting at position + /// @p Pos that are part of any liverange of physical register @p Reg or one + /// of its subregisters. + void removePhysRegDefAt(unsigned Reg, SlotIndex Pos); + + /// Remove value number and related live segments of @p LI and its subranges + /// that start at position @p Pos. + void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos); + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); @@ -404,6 +413,16 @@ namespace llvm { /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); + /// Walk the values in @p LI and check for dead values: + /// - Dead PHIDef values are marked as unused. + /// - Dead operands are marked as such. + /// - Completely dead machine instructions are added to the @p dead vector + /// if it is not nullptr. + /// Returns true if any PHI value numbers have been removed which may + /// have separated the interval into multiple connected components. + bool computeDeadValues(LiveInterval &LI, + SmallVectorImpl *dead); + static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; @@ -413,6 +432,16 @@ namespace llvm { void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + + /// Helper function for repairIntervalsInRange(), walks backwards and + /// creates/modifies live segments in @p LR to match the operands found. + /// Only full operands or operands with subregisters matching @p LaneMask + /// are considered. + void repairOldRegInRange(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + const SlotIndex endIdx, LiveRange &LR, + unsigned Reg, unsigned LaneMask = ~0u); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 2f40509..967f0cb 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -84,10 +84,16 @@ public: bool changedSince(unsigned tag) const { return tag != Tag; } // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg); + void unify(LiveInterval &VirtReg, const LiveRange &Range); + void unify(LiveInterval &VirtReg) { + unify(VirtReg, VirtReg); + } // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg); + void extract(LiveInterval &VirtReg, const LiveRange &Range); + void extract(LiveInterval &VirtReg) { + extract(VirtReg, VirtReg); + } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } @@ -173,8 +179,8 @@ public: } private: - Query(const Query&) LLVM_DELETED_FUNCTION; - void operator=(const Query&) LLVM_DELETED_FUNCTION; + Query(const Query&) = delete; + void operator=(const Query&) = delete; }; // Array of LiveIntervalUnions. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 91e4ddc..4aa53a9 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -44,8 +44,8 @@ class LivePhysRegs { const TargetRegisterInfo *TRI; SparseSet LiveRegs; - LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION; - LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION; + LivePhysRegs(const LivePhysRegs&) = delete; + LivePhysRegs &operator=(const LivePhysRegs&) = delete; public: /// \brief Constructs a new empty LivePhysRegs set. LivePhysRegs() : TRI(nullptr), LiveRegs() {} diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index e099e71..4131194 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -26,8 +26,8 @@ public: typedef DominanceFrontierBase::iterator iterator; typedef DominanceFrontierBase::const_iterator const_iterator; - void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; - MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + void operator=(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; static char ID; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 1e7fee6..6677360 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -516,6 +516,10 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); + /// Allocates memory at a fixed, target-specific offset from the frame + /// pointer. Marks the function as having its frame address taken. + int CreateFrameAllocation(uint64_t Size); + /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 3271410..94610ca 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -72,6 +72,15 @@ private: /// MachineFunction is destroyed. struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); + + /// \brief Factory function: default behavior is to call new using the + /// supplied allocator. + /// + /// This function can be overridden in a derive class. + template + static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { + return new (Allocator.Allocate()) Ty(MF); + } }; class MachineFunction { @@ -136,8 +145,8 @@ class MachineFunction { /// True if the function includes any inline assembly. bool HasInlineAsm; - MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; - void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; + MachineFunction(const MachineFunction &) = delete; + void operator=(const MachineFunction&) = delete; public: MachineFunction(const Function *Fn, const TargetMachine &TM, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -167,6 +176,13 @@ public: const TargetSubtargetInfo &getSubtarget() const { return *STI; } void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtargetInfo. In debug builds, it verifies that the object being + /// returned is of the correct type. + template const STC &getSubtarget() const { + return *static_cast(STI); + } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } @@ -239,7 +255,7 @@ public: template Ty *getInfo() { if (!MFInfo) - MFInfo = new (Allocator.Allocate()) Ty(*this); + MFInfo = Ty::template create(Allocator, *this); return static_cast(MFInfo); } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index d20b45b..4ba4a97 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -93,10 +93,10 @@ private: DebugLoc debugLoc; // Source line information. - MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION; - void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION; + MachineInstr(const MachineInstr&) = delete; + void operator=(const MachineInstr&) = delete; // Use MachineFunction::DeleteMachineInstr() instead. - ~MachineInstr() LLVM_DELETED_FUNCTION; + ~MachineInstr() = delete; // Intrusive list support friend struct ilist_traits; @@ -110,8 +110,8 @@ private: /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction&, const MCInstrDesc &MCID, - const DebugLoc dl, bool NoImp = false); + MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, + bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. friend class MachineFunction; @@ -242,7 +242,7 @@ public: /// getDebugLoc - Returns the debug location id of this MachineInstr. /// - DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// \brief Return the debug variable referenced by /// this DBG_VALUE instruction. @@ -1048,6 +1048,14 @@ public: bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); + /// Clear all dead flags on operands defining register @p Reg. + void clearRegisterDeads(unsigned Reg); + + /// Mark all subregister defs of register @p Reg with the undef flag. + /// This function is used when we determined to have a subregister def in an + /// otherwise undefined super register. + void addRegisterDefReadUndef(unsigned Reg); + /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. void addRegisterDefined(unsigned Reg, @@ -1139,7 +1147,10 @@ public: /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. /// - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { + debugLoc = std::move(dl); + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + } /// RemoveOperand - Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 4fbd46b..f7bcf45 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -74,8 +74,8 @@ class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase LI; friend class LoopBase; - void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; - MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MachineLoopInfo &) = delete; + MachineLoopInfo(const MachineLoopInfo &) = delete; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6653333..f171df2 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,6 +35,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" @@ -66,6 +67,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. + SmallVector ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative) @@ -161,14 +163,26 @@ class MachineModuleInfo : public ImmutablePass { /// to _fltused on Windows targets. bool UsesVAFloatArgument; + /// UsesMorestackAddr - True if the module calls the __morestack function + /// indirectly, as is required under the large code model on x86. This is used + /// to emit a definition of a symbol, __morestack_addr, containing the + /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more + /// details. + bool UsesMorestackAddr; + + EHPersonality PersonalityTypeCache; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingVH Var; - TrackingVH Expr; + TrackingMDNodeRef Var; + TrackingMDNodeRef Expr; unsigned Slot; DebugLoc Loc; + + VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector VariableDbgInfoMapTy; VariableDbgInfoMapTy VariableDbgInfos; @@ -231,6 +245,14 @@ public: UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \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. @@ -312,6 +334,11 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); + /// Add a clause for a landing pad. Returns a new label for the clause. This + /// is used by EH schemes that have more than one landing pad. In this case, + /// each clause gets its own basic block. + MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalValue *TI); @@ -389,12 +416,14 @@ public: /// of one is required to emit exception handling info. const Function *getPersonality() const; + /// Classify the personality function amongst known EH styles. + EHPersonality getPersonalityType(); + /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo Info = {Var, Expr, Slot, Loc}; - VariableDbgInfos.push_back(std::move(Info)); + VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index c962e68..57d1a6d 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -122,11 +122,12 @@ template class RegisterPassParser : public MachinePassRegistryListener, public cl::parser { public: - RegisterPassParser() {} + RegisterPassParser(cl::Option &O) + : cl::parser(O) {} ~RegisterPassParser() { RegistryClass::setListener(nullptr); } - void initialize(cl::Option &O) { - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add existing passes to option. for (RegistryClass *Node = RegistryClass::getList(); diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 2e7f034..abb04de 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -52,6 +52,9 @@ private: /// accurate when after this flag is cleared. bool TracksLiveness; + /// True if subregister liveness is tracked. + bool TracksSubRegLiveness; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -120,8 +123,8 @@ private: /// second element. std::vector > LiveIns; - MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; - void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; + MachineRegisterInfo(const MachineRegisterInfo&) = delete; + void operator=(const MachineRegisterInfo&) = delete; public: explicit MachineRegisterInfo(const MachineFunction *MF); @@ -179,6 +182,12 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } + bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + + void enableSubRegLiveness(bool Enable = true) { + TracksSubRegLiveness = Enable; + } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -584,7 +593,7 @@ public: /// virtual register, for example after removing instructions or splitting /// the live range. /// - bool recomputeRegClass(unsigned Reg, const TargetMachine&); + bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. @@ -768,6 +777,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); + /// Returns a mask covering all bits that can appear in lane masks of + /// subregisters of the virtual register @p Reg. + unsigned getMaxLaneMaskForVReg(unsigned Reg) const; + /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 486a26e..5f988ad 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -107,8 +107,8 @@ public: private: unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; - MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; + void operator=(const MachineSSAUpdater&) = delete; + MachineSSAUpdater(const MachineSSAUpdater&) = delete; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index c5f66a8..a319401 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -80,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index affacb0..7ad782f 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -118,6 +119,7 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + FIRST_VALUETYPE = 0, // This is always the beginning of the list. LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. @@ -150,7 +152,11 @@ namespace llvm { // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255 + iPTR = 255, + + // Any - Any type. This is used for intrinsics that have overloadings. + // This is only for tblgen's consumption! + Any = 256 }; SimpleValueType SimpleTy; @@ -165,6 +171,12 @@ namespace llvm { bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + /// isValid - Return true if this is a valid simple valuetype. + bool isValid() const { + return (SimpleTy >= MVT::FIRST_VALUETYPE && + SimpleTy < MVT::LAST_VALUETYPE); + } + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && @@ -237,7 +249,8 @@ namespace llvm { /// isOverloaded - Return true if this is an overloaded type for TableGen. bool isOverloaded() const { - return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || + return (SimpleTy==MVT::Any || + SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); } @@ -372,6 +385,7 @@ namespace llvm { case iAny: case fAny: case vAny: + case Any: llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); @@ -575,6 +589,52 @@ namespace llvm { /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); + private: + /// A simple iterator over the MVT::SimpleValueType enum. + struct mvt_iterator { + SimpleValueType VT; + mvt_iterator(SimpleValueType VT) : VT(VT) {} + MVT operator*() const { return VT; } + bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; } + mvt_iterator& operator++() { + VT = (MVT::SimpleValueType)((int)VT + 1); + assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE && + "MVT iterator overflowed."); + return *this; + } + }; + /// A range of the MVT::SimpleValueType enum. + typedef iterator_range mvt_range; + + public: + /// SimpleValueType Iteration + /// @{ + static mvt_range all_valuetypes() { + return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE); + } + static mvt_range integer_valuetypes() { + return mvt_range(MVT::FIRST_INTEGER_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1)); + } + static mvt_range fp_valuetypes() { + return mvt_range(MVT::FIRST_FP_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1)); + } + static mvt_range vector_valuetypes() { + return mvt_range(MVT::FIRST_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1)); + } + static mvt_range integer_vector_valuetypes() { + return mvt_range( + MVT::FIRST_INTEGER_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1)); + } + static mvt_range fp_vector_valuetypes() { + return mvt_range( + MVT::FIRST_FP_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1)); + } + /// @} }; } // End llvm namespace diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index 4dc5674..efb723c 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -507,14 +507,14 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// @brief Set an edge's cost matrix. + /// @brief Update an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template - void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) { + void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) { MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); if (Solver) - Solver->handleSetEdgeCosts(EId, *AllocatedCosts); + Solver->handleUpdateCosts(EId, *AllocatedCosts); getEdge(EId).Costs = AllocatedCosts; } @@ -548,14 +548,14 @@ namespace PBQP { /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. - NodeId getEdgeNode1Id(EdgeId EId) { + NodeId getEdgeNode1Id(EdgeId EId) const { return getEdge(EId).getN1Id(); } /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. - NodeId getEdgeNode2Id(EdgeId EId) { + NodeId getEdgeNode2Id(EdgeId EId) const { return getEdge(EId).getN2Id(); } @@ -672,69 +672,6 @@ namespace PBQP { Edges.clear(); FreeEdgeIds.clear(); } - - /// @brief Dump a graph to an output stream. - template - void dumpToStream(OStream &OS) { - OS << nodeIds().size() << " " << edgeIds().size() << "\n"; - - for (auto NId : nodeIds()) { - const Vector& V = getNodeCosts(NId); - OS << "\n" << V.getLength() << "\n"; - assert(V.getLength() != 0 && "Empty vector in graph."); - OS << V[0]; - for (unsigned i = 1; i < V.getLength(); ++i) { - OS << " " << V[i]; - } - OS << "\n"; - } - - for (auto EId : edgeIds()) { - NodeId N1Id = getEdgeNode1Id(EId); - NodeId N2Id = getEdgeNode2Id(EId); - assert(N1Id != N2Id && "PBQP graphs shound not have self-edges."); - const Matrix& M = getEdgeCosts(EId); - OS << "\n" << N1Id << " " << N2Id << "\n" - << M.getRows() << " " << M.getCols() << "\n"; - assert(M.getRows() != 0 && "No rows in matrix."); - assert(M.getCols() != 0 && "No cols in matrix."); - for (unsigned i = 0; i < M.getRows(); ++i) { - OS << M[i][0]; - for (unsigned j = 1; j < M.getCols(); ++j) { - OS << " " << M[i][j]; - } - OS << "\n"; - } - } - } - - /// @brief Dump this graph to dbgs(). - void dump() { - dumpToStream(dbgs()); - } - - /// @brief Print a representation of this graph in DOT format. - /// @param OS Output stream to print on. - template - void printDot(OStream &OS) { - OS << "graph {\n"; - for (auto NId : nodeIds()) { - OS << " node" << NId << " [ label=\"" - << NId << ": " << getNodeCosts(NId) << "\" ]\n"; - } - OS << " edge [ len=" << nodeIds().size() << " ]\n"; - for (auto EId : edgeIds()) { - OS << " node" << getEdgeNode1Id(EId) - << " -- node" << getEdgeNode2Id(EId) - << " [ label=\""; - const Matrix &EdgeCosts = getEdgeCosts(EId); - for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) { - OS << EdgeCosts.getRowAsVector(i) << "\\n"; - } - OS << "\" ]\n"; - } - OS << "}\n"; - } }; } // namespace PBQP diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21fde4d..d4a544b 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -132,9 +132,9 @@ namespace PBQP { } else { const Matrix &YZECosts = G.getEdgeCosts(YZEId); if (YNId == G.getEdgeNode1Id(YZEId)) { - G.setEdgeCosts(YZEId, Delta + YZECosts); + G.updateEdgeCosts(YZEId, Delta + YZECosts); } else { - G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); + G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts); } } @@ -144,6 +144,25 @@ namespace PBQP { // TODO: Try to normalize newly added/modified edge. } +#ifndef NDEBUG + // Does this Cost vector have any register options ? + template + bool hasRegisterOptions(const VectorT &V) { + unsigned VL = V.getLength(); + + // An empty or spill only cost vector does not provide any register option. + if (VL <= 1) + return false; + + // If there are registers in the cost vector, but all of them have infinite + // costs, then ... there is no available register. + for (unsigned i = 1; i < VL; ++i) + if (V[i] != std::numeric_limits::infinity()) + return true; + + return false; + } +#endif // \brief Find a solution to a fully reduced graph by backpropagation. // @@ -170,6 +189,15 @@ namespace PBQP { RawVector v = G.getNodeCosts(NId); +#ifndef NDEBUG + // Although a conservatively allocatable node can be allocated to a register, + // spilling it may provide a lower cost solution. Assert here that spilling + // is done by choice, not because there were no register available. + if (G.getNodeMetadata(NId).wasConservativelyAllocatable()) + assert(hasRegisterOptions(v) && "A conservatively allocatable node " + "must have available register options"); +#endif + for (auto EId : G.adjEdgeIds(NId)) { const Matrix& edgeCosts = G.getEdgeCosts(EId); if (NId == G.getEdgeNode1Id(EId)) { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index b672d9d..65b17d3 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -105,6 +105,7 @@ private: AnalysisID StopAfter; bool Started; bool Stopped; + bool AddingMachinePasses; protected: TargetMachine *TM; @@ -213,7 +214,7 @@ public: /// /// 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 new ScheduleDAGMI(C, make_unique(C), /* IsPostRA= */false) /// /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * @@ -259,12 +260,9 @@ protected: return false; } - /// addPreRegAlloc - This method may be implemented by targets that want to - /// run passes immediately before register allocation. This should return - /// true if -print-machineinstrs should print after these passes. - virtual bool addPreRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. @@ -290,24 +288,16 @@ protected: return false; } - /// addPostRegAlloc - This method may be implemented by targets that want to - /// run passes after register allocation pass pipeline but before - /// prolog-epilog insertion. This should return true if -print-machineinstrs - /// should print after these passes. - virtual bool addPostRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); - /// addPreSched2 - This method may be implemented by targets that want to - /// run passes after prolog-epilog insertion and before the second instruction - /// scheduling pass. This should return true if -print-machineinstrs should - /// print after these passes. - virtual bool addPreSched2() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after @@ -317,24 +307,30 @@ protected: /// Add standard basic block placement passes. virtual void addBlockPlacement(); - /// addPreEmitPass - This pass may be implemented by targets that want to run - /// passes immediately before machine code is emitted. This should return - /// true if -print-machineinstrs should print out the code after the passes. - virtual bool addPreEmitPass() { - return false; - } + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - void addPass(Pass *P); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -343,7 +339,14 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner); + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); }; } // namespace llvm @@ -351,13 +354,6 @@ protected: namespace llvm { FunctionPass *createAtomicExpandPass(const TargetMachine *TM); - /// \brief Create a basic TargetTransformInfo analysis pass. - /// - /// This pass implements the target transform info analysis using the target - /// independent information available to the LLVM code generator. - ImmutablePass * - createBasicTargetTransformInfoPass(const TargetMachine *TM); - /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either @@ -514,11 +510,15 @@ namespace llvm { /// information. extern char &MachineBlockPlacementStatsID; - /// GCLowering Pass - Performs target-independent LLVM IR transformations for - /// highly portable strategies. - /// + /// GCLowering Pass - Used by gc.root to perform its default lowering + /// operations. FunctionPass *createGCLoweringPass(); + /// ShadowStackGCLowering - Implements the custom lowering mechanism + /// used by the shadow stack GC. Only runs on functions which opt in to + /// the shadow stack collector. + FunctionPass *createShadowStackGCLoweringPass(); + /// GCMachineCodeAnalysis - Target-independent pass to mark safe points /// in machine code. Must be added very late during code generation, just /// prior to output, and importantly after all CFG transformations (such as @@ -560,12 +560,16 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); + FunctionPass *createMachineVerifierPass(const std::string& Banner); /// 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); + /// createWinEHPass - Prepares personality functions used by MSVC on Windows, + /// in addition to the Itanium LSDA based personalities. + FunctionPass *createWinEHPass(const TargetMachine *TM); + /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 540af08..c7bb07b 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -17,12 +17,15 @@ #define LLVM_CODEGEN_REGALLOCPBQP_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/PBQP/CostAllocator.h" #include "llvm/CodeGen/PBQP/ReductionRules.h" +#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { + +class raw_ostream; + namespace PBQP { namespace RegAlloc { @@ -177,23 +180,38 @@ class NodeMetadata { public: typedef RegAlloc::AllowedRegVector AllowedRegVector; - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; + // The node's reduction state. The order in this enum is important, + // as it is assumed nodes can only progress up (i.e. towards being + // optimally reducible) when reducing the graph. + typedef enum { + Unprocessed, + NotProvablyAllocatable, + ConservativelyAllocatable, + OptimallyReducible + } ReductionState; NodeMetadata() : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), - VReg(0) {} + VReg(0) +#ifndef NDEBUG + , everConservativelyAllocatable(false) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. NodeMetadata(const NodeMetadata &Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), - AllowedRegs(Other.AllowedRegs) { - std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], - &OptUnsafeEdges[0]); + AllowedRegs(Other.AllowedRegs) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + { + if (NumOpts > 0) { + std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], + &OptUnsafeEdges[0]); + } } // FIXME: Re-implementing default behavior to work around MSVC. Remove once @@ -201,7 +219,11 @@ public: NodeMetadata(NodeMetadata &&Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), - AllowedRegs(std::move(Other.AllowedRegs)) {} + AllowedRegs(std::move(Other.AllowedRegs)) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. @@ -214,6 +236,9 @@ public: OptUnsafeEdges.get()); VReg = Other.VReg; AllowedRegs = Other.AllowedRegs; +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -226,6 +251,9 @@ public: OptUnsafeEdges = std::move(Other.OptUnsafeEdges); VReg = Other.VReg; AllowedRegs = std::move(Other.AllowedRegs); +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -243,10 +271,21 @@ public: } ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } + void setReductionState(ReductionState RS) { + assert(RS >= this->RS && "A node's reduction state can not be downgraded"); + this->RS = RS; + +#ifndef NDEBUG + // Remember this state to assert later that a non-infinite register + // option was available. + if (RS == ConservativelyAllocatable) + everConservativelyAllocatable = true; +#endif + } + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -254,7 +293,7 @@ public: } void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts -= Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -267,6 +306,12 @@ public: &OptUnsafeEdges[NumOpts]); } +#ifndef NDEBUG + bool wasConservativelyAllocatable() const { + return everConservativelyAllocatable; + } +#endif + private: ReductionState RS; unsigned NumOpts; @@ -274,6 +319,10 @@ private: std::unique_ptr OptUnsafeEdges; unsigned VReg; GraphMetadata::AllowedRegVecRef AllowedRegs; + +#ifndef NDEBUG + bool everConservativelyAllocatable; +#endif }; class RegAllocSolverImpl { @@ -307,6 +356,8 @@ public: } void handleAddNode(NodeId NId) { + assert(G.getNodeCosts(NId).getLength() > 1 && + "PBQP Graph should not contain single or zero-option nodes"); G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); } void handleRemoveNode(NodeId NId) {} @@ -326,15 +377,7 @@ public: NodeMetadata& NMd = G.getNodeMetadata(NId); const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } + promote(NId, NMd); } void handleReconnectEdge(EdgeId EId, NodeId NId) { @@ -343,20 +386,44 @@ public: NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); } - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - + void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) { NodeId N1Id = G.getEdgeNode1Id(EId); NodeId N2Id = G.getEdgeNode2Id(EId); NodeMetadata& N1Md = G.getNodeMetadata(N1Id); NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + bool Transpose = N1Id != G.getEdgeNode1Id(EId); + + // Metadata are computed incrementally. First, update them + // by removing the old cost. + const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata(); + N1Md.handleRemoveEdge(OldMMd, Transpose); + N2Md.handleRemoveEdge(OldMMd, !Transpose); + + // And update now the metadata with the new cost. const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + N1Md.handleAddEdge(MMd, Transpose); + N2Md.handleAddEdge(MMd, !Transpose); + + // As the metadata may have changed with the update, the nodes may have + // become ConservativelyAllocatable or OptimallyReducible. + promote(N1Id, N1Md); + promote(N2Id, N2Md); } private: + void promote(NodeId NId, NodeMetadata& NMd) { + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + void removeFromCurrentSet(NodeId NId) { switch (G.getNodeMetadata(NId).getReductionState()) { case NodeMetadata::Unprocessed: break; @@ -497,6 +564,17 @@ private: typedef PBQP::Graph BaseT; public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} + + /// @brief Dump this graph to dbgs(). + void dump() const; + + /// @brief Dump this graph to an output stream. + /// @param OS Output stream to print on. + void dump(raw_ostream &OS) const; + + /// @brief Print a representation of this graph in DOT format. + /// @param OS Output stream to print on. + void printDot(raw_ostream &OS) const; }; inline Solution solve(PBQPRAGraph& G) { diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 5a65d59..80aee8c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -190,6 +190,12 @@ namespace llvm { return getKind() == Order && Contents.OrdKind == Barrier; } + /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory + /// dependence. + bool isNormalMemoryOrBarrier() const { + return (isNormalMemory() || isBarrier()); + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index fbdaf0d..dc1c80d 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -115,8 +115,8 @@ class SDDbgInfo { typedef DenseMap > DbgValMapType; DbgValMapType DbgValMap; - void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; - SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; + void operator=(const SDDbgInfo&) = delete; + SDDbgInfo(const SDDbgInfo&) = delete; public: SDDbgInfo() {} @@ -262,8 +262,8 @@ private: DenseSet &visited, int level, bool &printed); - void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION; - SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION; + void operator=(const SelectionDAG&) = delete; + SelectionDAG(const SelectionDAG&) = delete; public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); @@ -866,6 +866,12 @@ public: SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); + SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + SDValue Mask, SDValue Src0, EVT MemVT, + MachineMemOperand *MMO, ISD::LoadExtType); + SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, + SDValue Ptr, SDValue Mask, EVT MemVT, + MachineMemOperand *MMO, bool IsTrunc); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 2639402..d53e66d 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -18,8 +18,8 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { class FastISel; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 4715827..0b6240f 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,7 +19,6 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" @@ -145,7 +145,7 @@ public: bool operator<(const SDValue &O) const { return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); } - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Node != nullptr; } @@ -184,7 +184,7 @@ public: inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; - inline const DebugLoc getDebugLoc() const; + inline const DebugLoc &getDebugLoc() const; inline void dump() const; inline void dumpr() const; @@ -259,8 +259,8 @@ class SDUse { /// this operand. SDUse **Prev, *Next; - SDUse(const SDUse &U) LLVM_DELETED_FUNCTION; - void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; + SDUse(const SDUse &U) = delete; + void operator=(const SDUse &U) = delete; public: SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {} @@ -476,11 +476,11 @@ public: void setIROrder(unsigned Order) { IROrder = Order; } /// getDebugLoc - Return the source location info. - const DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// setDebugLoc - Set source location info. Try to avoid this, putting /// it in the constructor is preferable. - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } /// use_iterator - This class provides iterator support for SDUse /// operands that use a specific SDNode. @@ -754,19 +754,20 @@ protected: return Ret; } - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, ArrayRef Ops) - : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), - SubclassData(0), NodeId(-1), - OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), - ValueList(VTs.VTs), UseList(nullptr), - NumOperands(Ops.size()), NumValues(VTs.NumVTs), - debugLoc(dl), IROrder(Order) { + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), + OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), + ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), + NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); for (unsigned i = 0; i != Ops.size(); ++i) { + assert(OperandList && "no operands available"); OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -775,11 +776,12 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) { + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), + UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); } @@ -942,7 +944,7 @@ inline bool SDValue::use_empty() const { inline bool SDValue::hasOneUse() const { return Node->hasNUsesOfValue(1, ResNo); } -inline const DebugLoc SDValue::getDebugLoc() const { +inline const DebugLoc &SDValue::getDebugLoc() const { return Node->getDebugLoc(); } inline void SDValue::dump() const { @@ -1177,6 +1179,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || + N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE || N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } @@ -1413,6 +1417,12 @@ public: /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } + /// isInfinity - Return true if the value is an infinity + bool isInfinity() const { return Value->isInfinity(); } + + /// isNegative - Return true if the value is negative. + bool isNegative() const { return Value->isNegative(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1601,7 +1611,7 @@ public: /// BUILD_VECTORs. class BuildVectorSDNode : public SDNode { // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION; + explicit BuildVectorSDNode() = delete; public: /// isConstantSplat - Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is @@ -1926,6 +1936,81 @@ public: } }; +/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and +/// MSTORE nodes +/// +class MaskedLoadStoreSDNode : public MemSDNode { + // Operands + SDUse Ops[4]; +public: + friend class SelectionDAG; + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + InitOperands(Ops, Operands, numOperands); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value + // MaskedStoreSDNode (Chain, ptr, mask, data) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE; + } +}; + +/// MaskedLoadSDNode - This class is used to represent an MLOAD node +/// +class MaskedLoadSDNode : public MaskedLoadStoreSDNode { +public: + friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy, + EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + } + + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } + const SDValue &getSrc0() const { return getOperand(3); } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD; + } +}; + +/// MaskedStoreSDNode - This class is used to represent an MSTORE node +/// +class MaskedStoreSDNode : public MaskedLoadStoreSDNode { + +public: + friend class SelectionDAG; + MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + } + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } + + const SDValue &getValue() const { return getOperand(3); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSTORE; + } +}; + /// MachineSDNode - An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 00bb22b..9d6d6f5 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - LLVM_EXPLICIT operator bool() const { return isValid(); } + explicit operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index e343980..4e48afe 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -81,6 +81,52 @@ public: unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; +/// MI-level Statepoint operands +/// +/// Statepoint operands take the form: +/// , , [call arguments], +/// , , +/// , , [other args], +/// [gc values] +class StatepointOpers { +private: + enum { + NCallArgsPos = 0, + CallTargetPos = 1 + }; + +public: + explicit StatepointOpers(const MachineInstr *MI): + MI(MI) { } + + /// Get starting index of non call related arguments + /// (statepoint flags, vm state and gc state). + unsigned getVarIdx() const { + return MI->getOperand(NCallArgsPos).getImm() + 2; + } + + /// Returns the index of the operand containing the number of non-gc non-call + /// arguments. + unsigned getNumVMSArgsIdx() const { + return getVarIdx() + 3; + } + + /// Returns the number of non-gc non-call arguments attached to the + /// statepoint. Note that this is the number of arguments, not the number of + /// operands required to represent those arguments. + unsigned getNumVMSArgs() const { + return MI->getOperand(getNumVMSArgsIdx()).getImm(); + } + + /// Returns the target of the underlying call. + const MachineOperand &getCallTarget() const { + return MI->getOperand(CallTargetPos); + } + +private: + const MachineInstr *MI; +}; + class StackMaps { public: struct Location { @@ -132,6 +178,9 @@ public: /// \brief Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); + /// \brief Generate a stackmap record for a statepoint instruction. + void recordStatepoint(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. @@ -139,7 +188,6 @@ public: private: static const char *WSMP; - typedef SmallVector LocationVec; typedef SmallVector LiveOutVec; typedef MapVector ConstantPool; diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 87f1401..348c634 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -36,6 +36,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { bool UseInitArray; public: + TargetLoweringObjectFileELF() : UseInitArray(false) {} + virtual ~TargetLoweringObjectFileELF() {} void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, @@ -54,6 +56,13 @@ public: SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; + const MCSection * + getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; + + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + /// Return an MCExpr to use for a reference to the specified type info global /// variable from exception handling information. const MCExpr * @@ -89,8 +98,6 @@ public: ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - bool isSectionAtomizableBySymbols(const MCSection &Section) const override; - const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index b5fa0e8..756262f 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -98,3 +98,6 @@ def iAny : ValueType<0 , 254>; // Pseudo valuetype mapped to the current pointer size. def iPTR : ValueType<0 , 255>; + +// Pseudo valuetype to represent "any type of any size". +def Any : ValueType<0 , 256>; diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index eceb875..d7e9209 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -63,8 +63,8 @@ namespace llvm { /// createSpillSlot - Allocate a spill slot for RC from MFI. unsigned createSpillSlot(const TargetRegisterClass *RC); - VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION; - void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION; + VirtRegMap(const VirtRegMap&) = delete; + void operator=(const VirtRegMap&) = delete; public: static char ID; diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 37696eb..86ae8bb 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -6,9 +6,6 @@ /* Exported configuration */ #include "llvm/Config/llvm-config.h" -/* Patch version of the LLVM API */ -#cmakedefine LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} - /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" @@ -18,6 +15,9 @@ /* Define to enable crash overrides */ #cmakedefine ENABLE_CRASH_OVERRIDES +/* Define to disable C++ atexit */ +#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -52,6 +52,9 @@ don't. */ #cmakedefine01 HAVE_DECL_STRERROR_S +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +#cmakedefine HAVE_DIA_SDK ${HAVE_DIA_SDK} + /* Define to 1 if you have the header file, and it defines `DIR'. */ #cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H} @@ -219,6 +222,9 @@ /* 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 `mallctl` function. */ +#cmakedefine HAVE_MALLCTL ${HAVE_MALLCTL} + /* Define to 1 if you have the `mkdtemp' function. */ #cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} @@ -423,6 +429,9 @@ /* Have host's __chkstk */ #cmakedefine HAVE___CHKSTK ${HAVE___CHKSTK} +/* Have host's __chkstk_ms */ +#cmakedefine HAVE___CHKSTK_MS ${HAVE___CHKSTK_MS} + /* Have host's __cmpdi2 */ #cmakedefine HAVE___CMPDI2 ${HAVE___CMPDI2} @@ -459,6 +468,9 @@ /* Have host's ___chkstk */ #cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} +/* Have host's ___chkstk_ms */ +#cmakedefine HAVE____CHKSTK_MS ${HAVE____CHKSTK_MS} + /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS @@ -518,9 +530,6 @@ /* Type of 1st arg on ELM Callback */ #cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR} -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - /* Define to `int' if does not define. */ #undef pid_t @@ -542,7 +551,4 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Maximum path length */ -#cmakedefine MAXPATHLEN ${MAXPATHLEN} - #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 8fcf145..c317bb1 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -9,6 +9,9 @@ /* Define if we have libxml2 */ #undef CLANG_HAVE_LIBXML +/* Multilib suffix for libdir. */ +#undef CLANG_LIBDIR_SUFFIX + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR @@ -64,6 +67,9 @@ don't. */ #undef HAVE_DECL_STRERROR_S +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +#undef HAVE_DIA_SDK + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H @@ -204,6 +210,9 @@ /* Define if mallinfo() is available on this platform. */ #undef HAVE_MALLINFO +/* Define if mallctl() is available on this plaform. */ +#undef HAVE_MALLCTL + /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H @@ -417,6 +426,9 @@ /* Have host's __chkstk */ #undef HAVE___CHKSTK +/* Have host's __chkstk_ms */ +#undef HAVE___CHKSTK_MS + /* Have host's __cmpdi2 */ #undef HAVE___CMPDI2 @@ -453,6 +465,9 @@ /* Have host's ___chkstk */ #undef HAVE____CHKSTK +/* Have host's ___chkstk_ms */ +#undef HAVE____CHKSTK_MS + /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 77201e6..d54003d 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -87,10 +87,13 @@ #cmakedefine LLVM_USE_OPROFILE 1 /* Major version of the LLVM API */ -#cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} +#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} /* Minor version of the LLVM API */ -#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} + +/* Patch version of the LLVM API */ +#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} /* LLVM version string */ #define LLVM_VERSION_STRING "${PACKAGE_VERSION}" diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 2d6add7..25a9295 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -92,6 +92,9 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR +/* Patch version of the LLVM API */ +#undef LLVM_VERSION_PATCH + /* LLVM version string */ #undef LLVM_VERSION_STRING diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h deleted file mode 100644 index 3aa098d..0000000 --- a/include/llvm/DebugInfo/DIContext.h +++ /dev/null @@ -1,151 +0,0 @@ -//===-- DIContext.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 DIContext, an abstract data structure that holds -// debug information data. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_DICONTEXT_H -#define LLVM_DEBUGINFO_DICONTEXT_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" - -#include - -namespace llvm { - -class raw_ostream; - -/// DILineInfo - a format-neutral container for source line information. -struct DILineInfo { - std::string FileName; - std::string FunctionName; - uint32_t Line; - uint32_t Column; - - DILineInfo() - : FileName(""), FunctionName(""), Line(0), Column(0) {} - - bool operator==(const DILineInfo &RHS) const { - return Line == RHS.Line && Column == RHS.Column && - FileName == RHS.FileName && FunctionName == RHS.FunctionName; - } - bool operator!=(const DILineInfo &RHS) const { - return !(*this == RHS); - } -}; - -typedef SmallVector, 16> DILineInfoTable; - -/// DIInliningInfo - a format-neutral container for inlined code description. -class DIInliningInfo { - SmallVector Frames; - public: - DIInliningInfo() {} - DILineInfo getFrame(unsigned Index) const { - assert(Index < Frames.size()); - return Frames[Index]; - } - uint32_t getNumberOfFrames() const { - return Frames.size(); - } - void addFrame(const DILineInfo &Frame) { - Frames.push_back(Frame); - } -}; - -/// A DINameKind is passed to name search methods to specify a -/// preference regarding the type of name resolution the caller wants. -enum class DINameKind { None, ShortName, LinkageName }; - -/// DILineInfoSpecifier - controls which fields of DILineInfo container -/// should be filled with data. -struct DILineInfoSpecifier { - enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; - typedef DINameKind FunctionNameKind; - - FileLineInfoKind FLIKind; - FunctionNameKind FNKind; - - DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, - FunctionNameKind FNKind = FunctionNameKind::None) - : FLIKind(FLIKind), FNKind(FNKind) {} -}; - -/// Selects which debug sections get dumped. -enum DIDumpType { - DIDT_Null, - DIDT_All, - DIDT_Abbrev, - DIDT_AbbrevDwo, - DIDT_Aranges, - DIDT_Frames, - DIDT_Info, - DIDT_InfoDwo, - DIDT_Types, - DIDT_TypesDwo, - DIDT_Line, - DIDT_LineDwo, - DIDT_Loc, - DIDT_LocDwo, - DIDT_Ranges, - DIDT_Pubnames, - DIDT_Pubtypes, - DIDT_GnuPubnames, - DIDT_GnuPubtypes, - DIDT_Str, - DIDT_StrDwo, - DIDT_StrOffsetsDwo, - DIDT_AppleNames, - DIDT_AppleTypes, - DIDT_AppleNamespaces, - DIDT_AppleObjC -}; - -// In place of applying the relocations to the data we've read from disk we use -// a separate mapping table to the side and checking that at locations in the -// dwarf where we expect relocated values. This adds a bit of complexity to the -// dwarf parsing/extraction at the benefit of not allocating memory for the -// entire size of the debug info sections. -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. - static DIContext *getDWARFContext(const object::ObjectFile &Obj); - - virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; - - virtual DILineInfo getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; -private: - const DIContextKind Kind; -}; - -} - -#endif diff --git a/include/llvm/DebugInfo/DWARF/DIContext.h b/include/llvm/DebugInfo/DWARF/DIContext.h new file mode 100644 index 0000000..622aa69 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DIContext.h @@ -0,0 +1,150 @@ +//===-- DIContext.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 DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DILineInfo - a format-neutral container for source line information. +struct DILineInfo { + std::string FileName; + std::string FunctionName; + uint32_t Line; + uint32_t Column; + + DILineInfo() + : FileName(""), FunctionName(""), Line(0), Column(0) {} + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + FileName == RHS.FileName && FunctionName == RHS.FunctionName; + } + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } +}; + +typedef SmallVector, 16> DILineInfoTable; + +/// DIInliningInfo - a format-neutral container for inlined code description. +class DIInliningInfo { + SmallVector Frames; + public: + DIInliningInfo() {} + DILineInfo getFrame(unsigned Index) const { + assert(Index < Frames.size()); + return Frames[Index]; + } + uint32_t getNumberOfFrames() const { + return Frames.size(); + } + void addFrame(const DILineInfo &Frame) { + Frames.push_back(Frame); + } +}; + +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + +/// DILineInfoSpecifier - controls which fields of DILineInfo container +/// should be filled with data. +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + typedef DINameKind FunctionNameKind; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} +}; + +/// Selects which debug sections get dumped. +enum DIDumpType { + DIDT_Null, + DIDT_All, + DIDT_Abbrev, + DIDT_AbbrevDwo, + DIDT_Aranges, + DIDT_Frames, + DIDT_Info, + DIDT_InfoDwo, + DIDT_Types, + DIDT_TypesDwo, + DIDT_Line, + DIDT_LineDwo, + DIDT_Loc, + DIDT_LocDwo, + DIDT_Ranges, + DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, + DIDT_Str, + DIDT_StrDwo, + DIDT_StrOffsetsDwo, + DIDT_AppleNames, + DIDT_AppleTypes, + DIDT_AppleNamespaces, + DIDT_AppleObjC +}; + +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +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. + static DIContext *getDWARFContext(const object::ObjectFile &Obj); + + virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; + + virtual DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, + uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h new file mode 100644 index 0000000..bb05c30 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -0,0 +1,60 @@ +//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclaration { + uint32_t Code; + uint32_t Tag; + bool HasChildren; + + struct AttributeSpec { + AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} + uint16_t Attr; + uint16_t Form; + }; + typedef SmallVector AttributeSpecVector; + AttributeSpecVector AttributeSpecs; +public: + DWARFAbbreviationDeclaration(); + + uint32_t getCode() const { return Code; } + uint32_t getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + + typedef iterator_range + attr_iterator_range; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); + } + + uint16_t getFormByIndex(uint32_t idx) const { + return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; + } + + uint32_t findAttributeIndex(uint16_t attr) const; + bool extract(DataExtractor Data, uint32_t* OffsetPtr); + void dump(raw_ostream &OS) const; + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h new file mode 100644 index 0000000..e34f096 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -0,0 +1,49 @@ +//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include + +namespace llvm { + +class DWARFAcceleratorTable { + + struct Header { + uint32_t Magic; + uint16_t Version; + uint16_t HashFunction; + uint32_t NumBuckets; + uint32_t NumHashes; + uint32_t HeaderDataLength; + }; + + struct HeaderData { + typedef uint16_t AtomType; + typedef uint16_t Form; + uint32_t DIEOffsetBase; + SmallVector, 3> Atoms; + }; + + struct Header Hdr; + struct HeaderData HdrData; + DataExtractor AccelSection; + DataExtractor StringSection; + const RelocAddrMap& Relocs; +public: + DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection, + const RelocAddrMap &Relocs) + : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} + + bool extract(); + void dump(raw_ostream &OS) const; +}; + +} diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h new file mode 100644 index 0000000..743f9c6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -0,0 +1,31 @@ +//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" + +namespace llvm { + +class DWARFCompileUnit : public DWARFUnit { +public: + DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + void dump(raw_ostream &OS); + // VTable anchor. + ~DWARFCompileUnit() override; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h new file mode 100644 index 0000000..677242b --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -0,0 +1,292 @@ +//===-- DWARFContext.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H +#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include + +namespace llvm { + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through pure virtual +/// methods that a concrete implementation provides. +class DWARFContext : public DIContext { + + DWARFUnitSection CUs; + std::vector> TUs; + std::unique_ptr Abbrev; + std::unique_ptr Loc; + std::unique_ptr Aranges; + std::unique_ptr Line; + std::unique_ptr DebugFrame; + + DWARFUnitSection DWOCUs; + std::vector> DWOTUs; + std::unique_ptr AbbrevDWO; + std::unique_ptr LocDWO; + + DWARFContext(DWARFContext &) = delete; + DWARFContext &operator=(DWARFContext &) = delete; + + /// Read compile units from the debug_info section (if necessary) + /// and store them in CUs. + void parseCompileUnits(); + + /// Read type units from the debug_types sections (if necessary) + /// and store them in TUs. + void parseTypeUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and store them in DWOCUs. + void parseDWOCompileUnits(); + + /// Read type units from the debug_types.dwo section (if necessary) + /// and store them in DWOTUs. + void parseDWOTypeUnits(); + +public: + DWARFContext() : DIContext(CK_DWARF) {} + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_DWARF; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + typedef DWARFUnitSection::iterator_range cu_iterator_range; + typedef DWARFUnitSection::iterator_range tu_iterator_range; + typedef iterator_range>::iterator> tu_section_iterator_range; + + /// Get compile units in this context. + cu_iterator_range compile_units() { + parseCompileUnits(); + return cu_iterator_range(CUs.begin(), CUs.end()); + } + + /// Get type units in this context. + tu_section_iterator_range type_unit_sections() { + parseTypeUnits(); + return tu_section_iterator_range(TUs.begin(), TUs.end()); + } + + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { + parseDWOCompileUnits(); + return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + } + + /// Get type units in the DWO context. + tu_section_iterator_range dwo_type_unit_sections() { + parseDWOTypeUnits(); + return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseCompileUnits(); + return CUs.size(); + } + + /// Get the number of compile units in this context. + unsigned getNumTypeUnits() { + parseTypeUnits(); + return TUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOCompileUnits(); + return DWOCUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOTypeUnits(); + return DWOTUs.size(); + } + + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + parseCompileUnits(); + return CUs[index].get(); + } + + /// Get the compile unit at the specified index for the DWO compile units. + DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { + parseDWOCompileUnits(); + return DWOCUs[index].get(); + } + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLocDWO *getDebugLocDWO(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to the parsed frame information object. + const DWARFDebugFrame *getDebugFrame(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const = 0; + virtual const DWARFSection &getInfoSection() = 0; + typedef MapVector> TypeSectionMap; + virtual const TypeSectionMap &getTypesSections() = 0; + virtual StringRef getAbbrevSection() = 0; + virtual const DWARFSection &getLocSection() = 0; + virtual StringRef getARangeSection() = 0; + virtual StringRef getDebugFrameSection() = 0; + virtual const DWARFSection &getLineSection() = 0; + virtual StringRef getStringSection() = 0; + virtual StringRef getRangeSection() = 0; + virtual StringRef getPubNamesSection() = 0; + virtual StringRef getPubTypesSection() = 0; + virtual StringRef getGnuPubNamesSection() = 0; + virtual StringRef getGnuPubTypesSection() = 0; + + // Sections for DWARF5 split dwarf proposal. + virtual const DWARFSection &getInfoDWOSection() = 0; + virtual const TypeSectionMap &getTypesDWOSections() = 0; + virtual StringRef getAbbrevDWOSection() = 0; + virtual const DWARFSection &getLineDWOSection() = 0; + virtual const DWARFSection &getLocDWOSection() = 0; + virtual StringRef getStringDWOSection() = 0; + virtual StringRef getStringOffsetDWOSection() = 0; + virtual StringRef getRangeDWOSection() = 0; + virtual StringRef getAddrSection() = 0; + virtual const DWARFSection& getAppleNamesSection() = 0; + virtual const DWARFSection& getAppleTypesSection() = 0; + virtual const DWARFSection& getAppleNamespacesSection() = 0; + virtual const DWARFSection& getAppleObjCSection() = 0; + + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3 || version == 4; + } +private: + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + + /// Return the compile unit which contains instruction with provided + /// address. + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); +}; + +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { + virtual void anchor(); + bool IsLittleEndian; + uint8_t AddressSize; + DWARFSection InfoSection; + TypeSectionMap TypesSections; + StringRef AbbrevSection; + DWARFSection LocSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + DWARFSection LineSection; + StringRef StringSection; + StringRef RangeSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef GnuPubTypesSection; + + // Sections for DWARF5 split dwarf proposal. + DWARFSection InfoDWOSection; + TypeSectionMap TypesDWOSections; + StringRef AbbrevDWOSection; + DWARFSection LineDWOSection; + DWARFSection LocDWOSection; + StringRef StringDWOSection; + StringRef StringOffsetDWOSection; + StringRef RangeDWOSection; + StringRef AddrSection; + DWARFSection AppleNamesSection; + DWARFSection AppleTypesSection; + DWARFSection AppleNamespacesSection; + DWARFSection AppleObjCSection; + + SmallVector, 4> UncompressedSections; + +public: + DWARFContextInMemory(const object::ObjectFile &Obj); + bool isLittleEndian() const override { return IsLittleEndian; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() override { return InfoSection; } + const TypeSectionMap &getTypesSections() override { return TypesSections; } + StringRef getAbbrevSection() override { return AbbrevSection; } + const DWARFSection &getLocSection() override { return LocSection; } + StringRef getARangeSection() override { return ARangeSection; } + StringRef getDebugFrameSection() override { return DebugFrameSection; } + const DWARFSection &getLineSection() override { return LineSection; } + StringRef getStringSection() override { return StringSection; } + StringRef getRangeSection() override { return RangeSection; } + StringRef getPubNamesSection() override { return PubNamesSection; } + StringRef getPubTypesSection() override { return PubTypesSection; } + StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } + StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } + const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } + const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } + const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } + const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } + const TypeSectionMap &getTypesDWOSections() override { + return TypesDWOSections; + } + StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() override { return LineDWOSection; } + const DWARFSection &getLocDWOSection() override { return LocDWOSection; } + StringRef getStringDWOSection() override { return StringDWOSection; } + StringRef getStringOffsetDWOSection() override { + return StringOffsetDWOSection; + } + StringRef getRangeDWOSection() override { return RangeDWOSection; } + StringRef getAddrSection() override { + return AddrSection; + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h new file mode 100644 index 0000000..2114208 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -0,0 +1,63 @@ +//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include +#include +#include + +namespace llvm { + +class DWARFAbbreviationDeclarationSet { + uint32_t Offset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; + std::vector Decls; + +public: + DWARFAbbreviationDeclarationSet(); + + uint32_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor Data, uint32_t *OffsetPtr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); +}; + +class DWARFDebugAbbrev { + typedef std::map + DWARFAbbreviationDeclarationSetMap; + + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; + +public: + DWARFDebugAbbrev(); + + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + + void dump(raw_ostream &OS) const; + void extract(DataExtractor Data); + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h new file mode 100644 index 0000000..837a8e6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -0,0 +1,70 @@ +//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + // The total length of the entries for that set, not including the length + // field itself. + uint32_t Length; + // The offset from the beginning of the .debug_info section of the + // compilation unit entry referenced by the table. + uint32_t CuOffset; + // The DWARF version number. + uint16_t Version; + // The size in bytes of an address on the target architecture. For segmented + // addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + // The size in bytes of a segment descriptor on the target architecture. + // If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + uint64_t getEndAddress() const { return Address + Length; } + }; + +private: + typedef std::vector DescriptorColl; + typedef iterator_range desc_iterator_range; + + uint32_t Offset; + Header HeaderData; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + void clear(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h new file mode 100644 index 0000000..791f010 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -0,0 +1,87 @@ +//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + void generate(DWARFContext *CTX); + uint32_t findAddress(uint64_t Address) const; + +private: + void clear(); + void extract(DataExtractor DebugArangesData); + + // Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); + + struct Range { + explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, + uint32_t CUOffset = -1U) + : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} + + void setHighPC(uint64_t HighPC) { + if (HighPC == -1ULL || HighPC <= LowPC) + Length = 0; + else + Length = HighPC - LowPC; + } + uint64_t HighPC() const { + if (Length) + return LowPC + Length; + return -1ULL; + } + + bool containsAddress(uint64_t Address) const { + return LowPC <= Address && Address < HighPC(); + } + bool operator<(const Range &other) const { + return LowPC < other.LowPC; + } + + uint64_t LowPC; // Start of address range. + uint32_t Length; // End of address range (not including this address). + uint32_t CUOffset; // Offset of the compile unit or die. + }; + + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + + typedef std::vector RangeColl; + typedef RangeColl::const_iterator RangeCollIterator; + + std::vector Endpoints; + RangeColl Aranges; + DenseSet ParsedCUOffsets; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h new file mode 100644 index 0000000..be925cb --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -0,0 +1,43 @@ +//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { + +class FrameEntry; + +/// \brief A parsed .debug_frame section +/// +class DWARFDebugFrame { +public: + DWARFDebugFrame(); + ~DWARFDebugFrame(); + + /// \brief Dump the section data into the given stream. + void dump(raw_ostream &OS) const; + + /// \brief Parse the section from raw data. + /// data is assumed to be pointing to the beginning of the section. + void parse(DataExtractor Data); + +private: + std::vector> Entries; +}; + + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h new file mode 100644 index 0000000..1080327 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -0,0 +1,160 @@ +//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFDebugAranges; +class DWARFCompileUnit; +class DWARFUnit; +class DWARFContext; +class DWARFFormValue; +struct DWARFDebugInfoEntryInlinedChain; + +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. +class DWARFDebugInfoEntryMinimal { + /// Offset within the .debug_info of the start of this entry. + uint32_t Offset; + + /// How many to add to "this" to get the sibling. + uint32_t SiblingIdx; + + const DWARFAbbreviationDeclaration *AbbrevDecl; +public: + DWARFDebugInfoEntryMinimal() + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} + + void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, + unsigned indent = 0) const; + void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, + uint16_t attr, uint16_t form, unsigned indent = 0) const; + + /// Extracts a debug info entry, which is a child of a given unit, + /// starting at a given offset. If DIE can't be extracted, returns false and + /// doesn't change OffsetPtr. + bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); + + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } + + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + /// Returns true if DIE represents a subprogram or an inlined + /// subroutine. + bool isSubroutineDIE() const; + + uint32_t getOffset() const { return Offset; } + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + const DWARFDebugInfoEntryMinimal *getSibling() const { + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; + } + + // We know we are kept in a vector of contiguous entries, so we know + // we don't need to store our child pointer, if we have a child it will + // be the next entry in the list... + const DWARFDebugInfoEntryMinimal *getFirstChild() const { + return hasChildren() ? this + 1 : nullptr; + } + + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + SiblingIdx = Sibling - this; + } else + SiblingIdx = 0; + } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } + + bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, + DWARFFormValue &FormValue) const; + + const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, + const char *FailValue) const; + + uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, + uint64_t &HighPC) const; + + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const DWARFUnit *U, + const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), + /// returns its mangled name (or short name, if mangled is missing). + /// This name may be fetched from specification or abstract origin + /// for this subprogram. Returns null if no name is found. + const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or + /// DW_AT_abstract_origin references if necessary. + /// Returns null if no name is found. + const char *getName(const DWARFUnit *U, DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and + /// DW_AT_call_column from DIE (or zeroes if they are missing). + void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, + uint32_t &CallLine, uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + DWARFDebugInfoEntryInlinedChain + getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; +}; + +/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine +/// DIEs, (possibly ending with subprogram DIE), all of which are contained +/// in some concrete inlined instance tree. Address range for each DIE +/// (except the last DIE) in this chain is contained in address +/// range for next DIE in the chain. +struct DWARFDebugInfoEntryInlinedChain { + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} + SmallVector DIEs; + const DWARFUnit *U; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h new file mode 100644 index 0000000..0c564c4 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -0,0 +1,238 @@ +//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" +#include +#include +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLine { +public: + DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} + struct FileNameEntry { + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} + + const char *Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; + }; + + struct Prologue { + Prologue(); + + // The size in bytes of the statement information for this compilation unit + // (not including the total_length field itself). + uint32_t TotalLength; + // Version identifier for the statement information format. + uint16_t Version; + // The number of bytes following the prologue_length field to the beginning + // of the first byte of the statement program itself. + uint32_t PrologueLength; + // The size in bytes of the smallest target machine instruction. Statement + // program opcodes that alter the address register first multiply their + // operands by this value. + uint8_t MinInstLength; + // The maximum number of individual operations that may be encoded in an + // instruction. + uint8_t MaxOpsPerInst; + // The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + // This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + // This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + // The number assigned to the first special opcode. + uint8_t OpcodeBase; + std::vector StandardOpcodeLengths; + std::vector IncludeDirectories; + std::vector FileNames; + + // Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeof(TotalLength) + sizeof(Version) + + sizeof(PrologueLength); + } + // Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeof(TotalLength) - getLength(); + } + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + + void clear(); + void dump(raw_ostream &OS) const; + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); + }; + + // Standard .debug_line state machine structure. + struct Row { + explicit Row(bool default_is_stmt = false); + + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool default_is_stmt); + void dump(raw_ostream &OS) const; + + static bool orderByAddress(const Row& LHS, const Row& RHS) { + return LHS.Address < RHS.Address; + } + + // The program-counter value corresponding to a machine instruction + // generated by the compiler. + uint64_t Address; + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + uint32_t Line; + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the 'left edge' of the line. + uint16_t Column; + // An unsigned integer indicating the identity of the source file + // corresponding to a machine instruction. + uint16_t File; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; + // An unsigned integer representing the DWARF path discriminator value + // for this location. + uint32_t Discriminator; + // A boolean indicating that the current instruction is the beginning of a + // statement. + uint8_t IsStmt:1, + // A boolean indicating that the current instruction is the + // beginning of a basic block. + BasicBlock:1, + // A boolean indicating that the current address is that of the + // first byte after the end of a sequence of target machine + // instructions. + EndSequence:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an entry breakpoint + // of a function. + PrologueEnd:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an exit breakpoint + // of a function. + EpilogueBegin:1; + }; + + // Represents a series of contiguous machine instructions. Line table for each + // compilation unit may consist of multiple sequences, which are not + // guaranteed to be in the order of ascending instruction address. + struct Sequence { + // Sequence describes instructions at address range [LowPC, HighPC) + // and is described by line table rows [FirstRowIndex, LastRowIndex). + uint64_t LowPC; + uint64_t HighPC; + unsigned FirstRowIndex; + unsigned LastRowIndex; + bool Empty; + + Sequence(); + void reset(); + + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { + return LHS.LowPC < RHS.LowPC; + } + bool isValid() const { + return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); + } + bool containsPC(uint64_t pc) const { + return (LowPC <= pc && pc < HighPC); + } + }; + + struct LineTable { + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); + } + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); + } + + // Returns the index of the row with file/line info for a given address, + // or -1 if there is no such row. + uint32_t lookupAddress(uint64_t address) const; + + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector &result) const; + + // Extracts filename by its index in filename table in prologue. + // Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + + // Fills the Result argument with the file and line information + // corresponding to Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; + + void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); + + struct Prologue Prologue; + typedef std::vector RowVector; + typedef RowVector::const_iterator RowIter; + typedef std::vector SequenceVector; + typedef SequenceVector::const_iterator SequenceIter; + RowVector Rows; + SequenceVector Sequences; + }; + + const LineTable *getLineTable(uint32_t offset) const; + const LineTable *getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset); + +private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + + typedef std::map LineTableMapTy; + typedef LineTableMapTy::iterator LineTableIter; + typedef LineTableMapTy::const_iterator LineTableConstIter; + + const RelocAddrMap *RelocMap; + LineTableMapTy LineTableMap; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h new file mode 100644 index 0000000..bd44c2e5 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -0,0 +1,81 @@ +//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLoc { + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + /// A map used to resolve binary relocations. + const RelocAddrMap &RelocMap; + +public: + DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS) const; + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// specified address size to interpret the address ranges. + void parse(DataExtractor data, unsigned AddressSize); +}; + +class DWARFDebugLocDWO { + struct Entry { + uint64_t Start; + uint32_t Length; + SmallVector Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + LocationLists Locations; + +public: + void parse(DataExtractor data); + void dump(raw_ostream &OS) const; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h new file mode 100644 index 0000000..4ee3bda --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -0,0 +1,77 @@ +//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H + +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector> DWARFAddressRangesVector; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + // A beginning address offset. This address offset has the size of an + // address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the beginning + // of an address range. + uint64_t StartAddress; + // An ending address offset. This address offset again has the size of + // an address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the first + // address past the end of the address range. The ending address must + // be greater than or equal to the beginning address. + uint64_t EndAddress; + // The end of any given range list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset + // and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + // A base address selection entry consists of: + // 1. The value of the largest representable address offset + // (for example, 0xffffffff when the size of an address is 32 bits). + // 2. An address, which defines the appropriate base address for + // use in interpreting the beginning and ending address offsets of + // subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + // Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector Entries; + +public: + DWARFDebugRangeList() { clear(); } + void clear(); + void dump(raw_ostream &OS) const; + bool extract(DataExtractor data, uint32_t *offset_ptr); + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h new file mode 100644 index 0000000..5bb6d1b --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -0,0 +1,93 @@ +//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_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 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(nullptr) { + uval = 0; + } + + union { + uint64_t uval; + int64_t sval; + const char* cstr; + }; + const uint8_t* data; + }; + + uint16_t Form; // Form for this value. + ValueType Value; // Contains all data for the form. + +public: + DWARFFormValue(uint16_t Form = 0) : Form(Form) {} + uint16_t getForm() const { return Form; } + bool isFormClass(FormClass FC) const; + + void dump(raw_ostream &OS, const DWARFUnit *U) const; + + /// \brief extracts a value in data at offset *offset_ptr. + /// + /// The passed DWARFUnit is allowed to be nullptr, in which + /// case no relocation processing will be performed and some + /// kind of forms that depend on Unit information are disallowed. + /// \returns wether the extraction succeeded. + bool extractValue(DataExtractor data, uint32_t *offset_ptr, + const DWARFUnit *u); + bool isInlinedCStr() const { + return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; + } + + /// 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; + Optional> getAsBlock() const; + + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, + const DWARFUnit *u) const; + static bool skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, const DWARFUnit *u); + + static ArrayRef getFixedFormSizes(uint8_t AddrSize, + uint16_t Version); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h new file mode 100644 index 0000000..d7fe303 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -0,0 +1,22 @@ +//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H +#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +typedef DenseMap > RelocAddrMap; + +} // namespace llvm + +#endif + diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h new file mode 100644 index 0000000..f52004c --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -0,0 +1,24 @@ +//===-- DWARFSection.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H +#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H + +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" + +namespace llvm { + +struct DWARFSection { + StringRef Data; + RelocAddrMap Relocs; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h new file mode 100644 index 0000000..f24e278 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -0,0 +1,38 @@ +//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" + +namespace llvm { + +class DWARFTypeUnit : public DWARFUnit { +private: + uint64_t TypeHash; + uint32_t TypeOffset; +public: + DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } + void dump(raw_ostream &OS); +protected: + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; +}; + +} + +#endif + diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h new file mode 100644 index 0000000..628852f --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -0,0 +1,285 @@ +//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include + +namespace llvm { + +namespace object { +class ObjectFile; +} + +class DWARFContext; +class DWARFDebugAbbrev; +class DWARFUnit; +class StringRef; +class raw_ostream; + +/// Base class for all DWARFUnitSection classes. This provides the +/// functionality common to all unit types. +class DWARFUnitSectionBase { +public: + /// Returns the Unit that contains the given section offset in the + /// same section this Unit originated from. + virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + + void parse(DWARFContext &C, const DWARFSection &Section); + void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); + +protected: + virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; + + ~DWARFUnitSectionBase() {} +}; + +/// Concrete instance of DWARFUnitSection, specialized for one Unit type. +template +class DWARFUnitSection final : public SmallVector, 1>, + public DWARFUnitSectionBase { + + struct UnitOffsetComparator { + bool operator()(uint32_t LHS, + const std::unique_ptr &RHS) const { + return LHS < RHS->getNextUnitOffset(); + } + }; + + bool Parsed; + +public: + DWARFUnitSection() : Parsed(false) {} + DWARFUnitSection(DWARFUnitSection &&DUS) : + SmallVector, 1>(std::move(DUS)), Parsed(DUS.Parsed) {} + + typedef llvm::SmallVectorImpl> UnitVector; + typedef typename UnitVector::iterator iterator; + typedef llvm::iterator_range iterator_range; + + UnitType *getUnitForOffset(uint32_t Offset) const override { + auto *CU = std::upper_bound(this->begin(), this->end(), Offset, + UnitOffsetComparator()); + if (CU != this->end()) + return CU->get(); + return nullptr; + } + +private: + void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE) override { + if (Parsed) + return; + DataExtractor Data(Section.Data, LE, 0); + uint32_t Offset = 0; + while (Data.isValidOffset(Offset)) { + auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, + AOS, LE, *this); + if (!U->extract(Data, &Offset)) + break; + this->push_back(std::move(U)); + Offset = this->back()->getNextUnitOffset(); + } + Parsed = true; + } +}; + +class DWARFUnit { + DWARFContext &Context; + // Section containing this DWARFUnit. + const DWARFSection &InfoSection; + + const DWARFDebugAbbrev *Abbrev; + StringRef RangeSection; + uint32_t RangeSectionBase; + StringRef StringSection; + StringRef StringOffsetSection; + StringRef AddrOffsetSection; + uint32_t AddrOffsetSectionBase; + bool isLittleEndian; + const DWARFUnitSectionBase &UnitSection; + + uint32_t Offset; + uint32_t Length; + uint16_t Version; + const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t AddrSize; + uint64_t BaseAddr; + // The compile unit debug information entry items. + std::vector DieArray; + + class DWOHolder { + object::OwningBinary DWOFile; + std::unique_ptr DWOContext; + DWARFUnit *DWOU; + public: + DWOHolder(StringRef DWOPath); + DWARFUnit *getUnit() const { return DWOU; } + }; + std::unique_ptr DWO; + +protected: + virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } + +public: + DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection); + + virtual ~DWARFUnit(); + + DWARFContext& getContext() const { return Context; } + + StringRef getStringSection() const { return StringSection; } + StringRef getStringOffsetSection() const { return StringOffsetSection; } + void setAddrOffsetSection(StringRef AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + void setRangesSection(StringRef RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + // FIXME: Result should be uint64_t in DWARF64. + bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; + + DataExtractor getDebugInfoExtractor() const { + return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); + } + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + + const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } + + bool extract(DataExtractor debug_info, uint32_t* offset_ptr); + + /// extractRangeList - extracts the range list referenced by this compile + /// unit from .debug_ranges section. Returns true on success. + /// Requires that compile unit is already extracted. + bool extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; + void clear(); + uint32_t getOffset() const { return Offset; } + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getLength() const { return Length; } + uint16_t getVersion() const { return Version; } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const { + return Abbrevs; + } + uint8_t getAddressByteSize() const { return AddrSize; } + uint64_t getBaseAddress() const { return BaseAddr; } + + void setBaseAddress(uint64_t base_addr) { + BaseAddr = base_addr; + } + + const DWARFDebugInfoEntryMinimal * + getCompileUnitDIE(bool extract_cu_die_only = true) { + extractDIEsIfNeeded(extract_cu_die_only); + return DieArray.empty() ? nullptr : &DieArray[0]; + } + + const char *getCompilationDir(); + uint64_t getDWOId(); + + void collectAddressRanges(DWARFAddressRangesVector &CURanges); + + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. + DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + + /// getUnitSection - Return the DWARFUnitSection containing this unit. + const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + + /// \brief Returns the number of DIEs in the unit. Parses the unit + /// if necessary. + unsigned getNumDIEs() { + extractDIEsIfNeeded(false); + return DieArray.size(); + } + + /// \brief Return the index of a DIE inside the unit's DIE vector. + /// + /// It is illegal to call this method with a DIE that hasn't be + /// created by this unit. In other word, it's illegal to call this + /// method on a DIE that isn't accessible by following + /// children/sibling links starting from this unit's + /// getCompileUnitDIE(). + uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { + assert(!DieArray.empty() && DIE >= &DieArray[0] && + DIE < &DieArray[0] + DieArray.size()); + return DIE - &DieArray[0]; + } + + /// \brief Return the DIE object at the given index. + const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const { + assert(Index < DieArray.size()); + return &DieArray[Index]; + } + + /// \brief Return the DIE object for a given offset inside the + /// unit's DIE vector. + /// + /// The unit needs to have his DIEs extracted for this method to work. + const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const { + assert(!DieArray.empty()); + auto it = std::lower_bound( + DieArray.begin(), DieArray.end(), Offset, + [=](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) { + return LHS.getOffset() < Offset; + }); + return it == DieArray.end() ? nullptr : &*it; + } + +private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. Returns the number of DIEs parsed at this call. + size_t extractDIEsIfNeeded(bool CUDieOnly); + /// extractDIEsToVector - Appends all parsed DIEs to a vector. + void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, + std::vector &DIEs) const; + /// setDIERelations - We read in all of the DIE entries into our flat list + /// of DIE entries and now we need to go back through all of them and set the + /// parent, sibling and child pointers for quick DIE navigation. + void setDIERelations(); + /// clearDIEs - Clear parsed DIEs to keep memory usage low. + void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); + + /// getSubprogramForAddress - Returns subprogram DIE with address range + /// encompassing the provided address. The pointer is alive as long as parsed + /// compile unit DIEs are not cleared. + const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h deleted file mode 100644 index 5bb6d1b..0000000 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ /dev/null @@ -1,93 +0,0 @@ -//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_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 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(nullptr) { - uval = 0; - } - - union { - uint64_t uval; - int64_t sval; - const char* cstr; - }; - const uint8_t* data; - }; - - uint16_t Form; // Form for this value. - ValueType Value; // Contains all data for the form. - -public: - DWARFFormValue(uint16_t Form = 0) : Form(Form) {} - uint16_t getForm() const { return Form; } - bool isFormClass(FormClass FC) const; - - void dump(raw_ostream &OS, const DWARFUnit *U) const; - - /// \brief extracts a value in data at offset *offset_ptr. - /// - /// The passed DWARFUnit is allowed to be nullptr, in which - /// case no relocation processing will be performed and some - /// kind of forms that depend on Unit information are disallowed. - /// \returns wether the extraction succeeded. - bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFUnit *u); - bool isInlinedCStr() const { - return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; - } - - /// 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; - Optional> getAsBlock() const; - - bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFUnit *u) const; - static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFUnit *u); - - static ArrayRef getFixedFormSizes(uint8_t AddrSize, - uint16_t Version); -}; - -} - -#endif diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h new file mode 100644 index 0000000..96ce12f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -0,0 +1,59 @@ +//===- ConcreteSymbolEnumerator.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H + +#include "IPDBEnumChildren.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +template +class ConcreteSymbolEnumerator : public IPDBEnumChildren { +public: + ConcreteSymbolEnumerator(std::unique_ptr SymbolEnumerator) + : Enumerator(std::move(SymbolEnumerator)) {} + + virtual ~ConcreteSymbolEnumerator() {} + + uint32_t getChildCount() const override { + return Enumerator->getChildCount(); + } + + std::unique_ptr getChildAtIndex(uint32_t Index) const override { + std::unique_ptr Child = Enumerator->getChildAtIndex(Index); + return make_concrete_child(std::move(Child)); + } + + std::unique_ptr getNext() override { + std::unique_ptr Child = Enumerator->getNext(); + return make_concrete_child(std::move(Child)); + } + + void reset() override { Enumerator->reset(); } + + ConcreteSymbolEnumerator *clone() const override { + std::unique_ptr WrappedClone(Enumerator->clone()); + return new ConcreteSymbolEnumerator(std::move(WrappedClone)); + } + +private: + std::unique_ptr + make_concrete_child(std::unique_ptr Child) const { + ChildType *ConcreteChild = dyn_cast_or_null(Child.release()); + return std::unique_ptr(ConcreteChild); + } + + std::unique_ptr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h new file mode 100644 index 0000000..7b2bc14 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -0,0 +1,33 @@ +//===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H +#define LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBDataStream.h" + +namespace llvm { +class DIADataStream : public IPDBDataStream { +public: + explicit DIADataStream(CComPtr DiaStreamData); + + uint32_t getRecordCount() const override; + std::string getName() const override; + llvm::Optional getItemAtIndex(uint32_t Index) const override; + bool getNext(RecordType &Record) override; + void reset() override; + DIADataStream *clone() const override; + +private: + CComPtr StreamData; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h new file mode 100644 index 0000000..375bcdd --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -0,0 +1,35 @@ +//==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBDataStream; + +class DIAEnumDebugStreams : public IPDBEnumChildren { +public: + explicit DIAEnumDebugStreams(CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumDebugStreams *clone() const override; + +private: + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h new file mode 100644 index 0000000..4cc85ed --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -0,0 +1,35 @@ +//==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBLineNumber; + +class DIAEnumLineNumbers : public IPDBEnumChildren { +public: + explicit DIAEnumLineNumbers(CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumLineNumbers *clone() const override; + +private: + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h new file mode 100644 index 0000000..88625f6 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -0,0 +1,37 @@ +//==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSourceFiles : public IPDBEnumChildren { +public: + explicit DIAEnumSourceFiles(const DIASession &PDBSession, + CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumSourceFiles *clone() const override; + +private: + const DIASession &Session; + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h new file mode 100644 index 0000000..fe343f7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -0,0 +1,37 @@ +//==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSymbols : public IPDBEnumChildren { +public: + explicit DIAEnumSymbols(const DIASession &Session, + CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + DIAEnumSymbols *clone() const override; + +private: + const DIASession &Session; + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h new file mode 100644 index 0000000..5950a0d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h @@ -0,0 +1,39 @@ +//===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H +#define LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" + +namespace llvm { +class DIALineNumber : public IPDBLineNumber { +public: + explicit DIALineNumber(CComPtr DiaLineNumber); + + uint32_t getLineNumber() const override; + uint32_t getLineNumberEnd() const override; + uint32_t getColumnNumber() const override; + uint32_t getColumnNumberEnd() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + uint32_t getSourceFileId() const override; + uint32_t getCompilandId() const override; + bool isStatement() const override; + +private: + CComPtr LineNumber; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h new file mode 100644 index 0000000..c71f35c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -0,0 +1,206 @@ +//===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" + +namespace llvm { +class DIASession; +class DIARawSymbol : public IPDBRawSymbol { +public: + DIARawSymbol(const DIASession &PDBSession, CComPtr DiaSymbol); + + void dump(raw_ostream &OS, int Indent) const override; + + CComPtr getDiaSymbol() const { return Symbol; } + + std::unique_ptr + DIARawSymbol::findChildren(PDB_SymType Type) const override; + std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override; + std::unique_ptr + findInlineFramesByRVA(uint32_t RVA) const override; + + void getDataBytes(llvm::SmallVector &bytes) const override; + void getFrontEndVersion(VersionInfo &Version) const override; + void getBackEndVersion(VersionInfo &Version) const override; + PDB_MemberAccess getAccess() const override; + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getAge() const override; + uint32_t getArrayIndexTypeId() const override; + uint32_t getBaseDataOffset() const override; + uint32_t getBaseDataSlot() const override; + uint32_t getBaseSymbolId() const override; + PDB_BuiltinType getBuiltinType() const override; + uint32_t getBitPosition() const override; + PDB_CallingConv getCallingConvention() const override; + uint32_t getClassParentId() const override; + std::string getCompilerName() const override; + uint32_t getCount() const override; + uint32_t getCountLiveRanges() const override; + PDB_Lang getLanguage() const override; + uint32_t getLexicalParentId() const override; + std::string getLibraryName() const override; + uint32_t getLiveRangeStartAddressOffset() const override; + uint32_t getLiveRangeStartAddressSection() const override; + uint32_t getLiveRangeStartRelativeVirtualAddress() const override; + PDB_RegisterId getLocalBasePointerRegisterId() const override; + uint32_t getLowerBoundId() const override; + uint32_t getMemorySpaceKind() const override; + std::string getName() const override; + uint32_t getNumberOfAcceleratorPointerTags() const override; + uint32_t getNumberOfColumns() const override; + uint32_t getNumberOfModifiers() const override; + uint32_t getNumberOfRegisterIndices() const override; + uint32_t getNumberOfRows() const override; + std::string getObjectFileName() const override; + uint32_t getOemId() const override; + uint32_t getOemSymbolId() const override; + uint32_t getOffsetInUdt() const override; + PDB_Cpu getPlatform() const override; + uint32_t getRank() const override; + PDB_RegisterId getRegisterId() const override; + uint32_t getRegisterType() const override; + uint32_t getRelativeVirtualAddress() const override; + uint32_t getSamplerSlot() const override; + uint32_t getSignature() const override; + uint32_t getSizeInUdt() const override; + uint32_t getSlot() const override; + std::string getSourceFileName() const override; + uint32_t getStride() const override; + uint32_t getSubTypeId() const override; + std::string getSymbolsFileName() const override; + uint32_t getSymIndexId() const override; + uint32_t getTargetOffset() const override; + uint32_t getTargetRelativeVirtualAddress() const override; + uint64_t getTargetVirtualAddress() const override; + uint32_t getTargetSection() const override; + uint32_t getTextureSlot() const override; + uint32_t getTimeStamp() const override; + uint32_t getToken() const override; + uint32_t getTypeId() const override; + uint32_t getUavSlot() const override; + std::string getUndecoratedName() const override; + uint32_t getUnmodifiedTypeId() const override; + uint32_t getUpperBoundId() const override; + Variant getValue() const override; + uint32_t getVirtualBaseDispIndex() const override; + uint32_t getVirtualBaseOffset() const override; + uint32_t getVirtualTableShapeId() const override; + PDB_DataKind getDataKind() const override; + PDB_SymType getSymTag() const override; + PDB_UniqueId getGuid() const override; + int32_t getOffset() const override; + int32_t getThisAdjust() const override; + int32_t getVirtualBasePointerOffset() const override; + PDB_LocType getLocationType() const override; + PDB_Machine getMachineType() const override; + PDB_ThunkOrdinal getThunkOrdinal() const override; + uint64_t getLength() const override; + uint64_t getLiveRangeLength() const override; + uint64_t getVirtualAddress() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool hasCustomCallingConvention() const override; + bool hasFarReturn() const override; + bool isCode() const override; + bool isCompilerGenerated() const override; + bool isConstType() const override; + bool isEditAndContinueEnabled() const override; + bool isFunction() const override; + bool getAddressTaken() const override; + bool getNoStackOrdering() const override; + bool hasAlloca() const override; + bool hasAssignmentOperator() const override; + bool hasCTypes() const override; + bool hasCastOperator() const override; + bool hasDebugInfo() const override; + bool hasEH() const override; + bool hasEHa() const override; + bool hasInlAsm() const override; + bool hasInlineAttribute() const override; + bool hasInterruptReturn() const override; + bool hasFramePointer() const override; + bool hasLongJump() const override; + bool hasManagedCode() const override; + bool hasNestedTypes() const override; + bool hasNoInlineAttribute() const override; + bool hasNoReturnAttribute() const override; + bool hasOptimizedCodeDebugInfo() const override; + bool hasOverloadedOperator() const override; + bool hasSEH() const override; + bool hasSecurityChecks() const override; + bool hasSetJump() const override; + bool hasStrictGSCheck() const override; + bool isAcceleratorGroupSharedLocal() const override; + bool isAcceleratorPointerTagLiveRange() const override; + bool isAcceleratorStubFunction() const override; + bool isAggregated() const override; + bool isIntroVirtualFunction() const override; + bool isCVTCIL() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isDataAligned() const override; + bool isHLSLData() const override; + bool isHotpatchable() const override; + bool isIndirectVirtualBaseClass() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isLTCG() const override; + bool isLocationControlFlowDependent() const override; + bool isMSILNetmodule() const override; + bool isMatrixRowMajor() const override; + bool isManagedCode() const override; + bool isMSILCode() const override; + bool isMultipleInheritance() const override; + bool isNaked() const override; + bool isNested() const override; + bool isOptimizedAway() const override; + bool isPacked() const override; + bool isPointerBasedOnSymbolValue() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + bool isPureVirtual() const override; + bool isRValueReference() const override; + bool isRefUdt() const override; + bool isReference() const override; + bool isRestrictedType() const override; + bool isReturnValue() const override; + bool isSafeBuffers() const override; + bool isScoped() const override; + bool isSdl() const override; + bool isSingleInheritance() const override; + bool isSplitted() const override; + bool isStatic() const override; + bool hasPrivateSymbols() const override; + bool isUnalignedType() const override; + bool isUnreached() const override; + bool isValueUdt() const override; + bool isVirtual() const override; + bool isVirtualBaseClass() const override; + bool isVirtualInheritance() const override; + bool isVolatileType() const override; + bool wasInlined() const override; + std::string getUnused() const override; + +private: + const DIASession &Session; + CComPtr Symbol; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h new file mode 100644 index 0000000..141b9b0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -0,0 +1,42 @@ +//===- DIASession.h - DIA implementation of IPDBSession ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H + +#include "DIASupport.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" + +namespace llvm { +class DIASession : public IPDBSession { +public: + explicit DIASession(CComPtr DiaSession); + + static DIASession *createFromPdb(StringRef Path); + + uint64_t getLoadAddress() const override; + void setLoadAddress(uint64_t Address) override; + std::unique_ptr getGlobalScope() const override; + std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + + std::unique_ptr getAllSourceFiles() const override; + std::unique_ptr getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr getDebugStreams() const override; + +private: + CComPtr Session; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h new file mode 100644 index 0000000..c424e27 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h @@ -0,0 +1,36 @@ +//===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +namespace llvm { +class DIASession; + +class DIASourceFile : public IPDBSourceFile { +public: + explicit DIASourceFile(const DIASession &Session, + CComPtr DiaSourceFile); + + std::string getFileName() const override; + uint32_t getUniqueId() const override; + std::string getChecksum() const override; + PDB_Checksum getChecksumType() const override; + std::unique_ptr getCompilands() const override; + +private: + const DIASession &Session; + CComPtr SourceFile; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h new file mode 100644 index 0000000..407a345 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -0,0 +1,33 @@ +//===- DIASupport.h - Common header includes for DIA ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Common defines and header includes for all LLVMDebugInfoPDBDIA. The +// definitions here configure the necessary #defines and include system headers +// in the proper order for using DIA. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H + +// Require at least Vista +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA +#define WINVER _WIN32_WINNT_VISTA +#ifndef NOMINMAX +#define NOMINMAX +#endif + +// atlbase.h has to come before windows.h +#include +#include + +// DIA headers must come after windows headers. +#include +#include + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h new file mode 100644 index 0000000..808a0f3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -0,0 +1,37 @@ +//===- IPDBDataStream.h - base interface for child enumerator -*- C++ ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H +#define LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H + +#include "PDBTypes.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +/// IPDBDataStream defines an interface used to represent a stream consisting +/// of a name and a series of records whose formats depend on the particular +/// stream type. +class IPDBDataStream { +public: + typedef llvm::SmallVector RecordType; + + virtual ~IPDBDataStream(); + + virtual uint32_t getRecordCount() const = 0; + virtual std::string getName() const = 0; + virtual llvm::Optional getItemAtIndex(uint32_t Index) const = 0; + virtual bool getNext(RecordType &Record) = 0; + virtual void reset() = 0; + virtual IPDBDataStream *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h new file mode 100644 index 0000000..645ac96 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -0,0 +1,33 @@ +//===- IPDBEnumChildren.h - base interface for child enumerator -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H +#define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H + +#include "PDBTypes.h" +#include + +namespace llvm { + +template class IPDBEnumChildren { +public: + typedef std::unique_ptr ChildTypePtr; + typedef IPDBEnumChildren MyType; + + virtual ~IPDBEnumChildren() {} + + virtual uint32_t getChildCount() const = 0; + virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; + virtual ChildTypePtr getNext() = 0; + virtual void reset() = 0; + virtual MyType *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h new file mode 100644 index 0000000..92cd58d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h @@ -0,0 +1,36 @@ +//===- IPDBLineNumber.h - base interface for PDB line no. 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_DEBUGINFO_PDB_IPDBLINENUMBER_H +#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H + +#include "PDBTypes.h" + +namespace llvm { + +class IPDBLineNumber { +public: + virtual ~IPDBLineNumber(); + + virtual uint32_t getLineNumber() const = 0; + virtual uint32_t getLineNumberEnd() const = 0; + virtual uint32_t getColumnNumber() const = 0; + virtual uint32_t getColumnNumberEnd() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual uint32_t getSourceFileId() const = 0; + virtual uint32_t getCompilandId() const = 0; + virtual bool isStatement() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h new file mode 100644 index 0000000..139bff5 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -0,0 +1,211 @@ +//===- IPDBRawSymbol.h - base interface for PDB symbol types ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H + +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +class raw_ostream; + +/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. +/// It exposes a monolithic interface consisting of accessors for the union of +/// all properties that are valid for any symbol type. This interface is then +/// wrapped by a concrete class which exposes only those set of methods valid +/// for this particular symbol type. See PDBSymbol.h for more details. +class IPDBRawSymbol { +public: + virtual ~IPDBRawSymbol(); + + virtual void dump(raw_ostream &OS, int Indent) const = 0; + + virtual std::unique_ptr + findChildren(PDB_SymType Type) const = 0; + + virtual std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const = 0; + virtual std::unique_ptr + findInlineFramesByRVA(uint32_t RVA) const = 0; + + virtual void getDataBytes(llvm::SmallVector &bytes) const = 0; + virtual void getBackEndVersion(VersionInfo &Version) const = 0; + virtual PDB_MemberAccess getAccess() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAge() const = 0; + virtual uint32_t getArrayIndexTypeId() const = 0; + virtual uint32_t getBaseDataOffset() const = 0; + virtual uint32_t getBaseDataSlot() const = 0; + virtual uint32_t getBaseSymbolId() const = 0; + virtual PDB_BuiltinType getBuiltinType() const = 0; + virtual uint32_t getBitPosition() const = 0; + virtual PDB_CallingConv getCallingConvention() const = 0; + virtual uint32_t getClassParentId() const = 0; + virtual std::string getCompilerName() const = 0; + virtual uint32_t getCount() const = 0; + virtual uint32_t getCountLiveRanges() const = 0; + virtual void getFrontEndVersion(VersionInfo &Version) const = 0; + virtual PDB_Lang getLanguage() const = 0; + virtual uint32_t getLexicalParentId() const = 0; + virtual std::string getLibraryName() const = 0; + virtual uint32_t getLiveRangeStartAddressOffset() const = 0; + virtual uint32_t getLiveRangeStartAddressSection() const = 0; + virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0; + virtual PDB_RegisterId getLocalBasePointerRegisterId() const = 0; + virtual uint32_t getLowerBoundId() const = 0; + virtual uint32_t getMemorySpaceKind() const = 0; + virtual std::string getName() const = 0; + virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0; + virtual uint32_t getNumberOfColumns() const = 0; + virtual uint32_t getNumberOfModifiers() const = 0; + virtual uint32_t getNumberOfRegisterIndices() const = 0; + virtual uint32_t getNumberOfRows() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual uint32_t getOemId() const = 0; + virtual uint32_t getOemSymbolId() const = 0; + virtual uint32_t getOffsetInUdt() const = 0; + virtual PDB_Cpu getPlatform() const = 0; + virtual uint32_t getRank() const = 0; + virtual PDB_RegisterId getRegisterId() const = 0; + virtual uint32_t getRegisterType() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint32_t getSamplerSlot() const = 0; + virtual uint32_t getSignature() const = 0; + virtual uint32_t getSizeInUdt() const = 0; + virtual uint32_t getSlot() const = 0; + virtual std::string getSourceFileName() const = 0; + virtual uint32_t getStride() const = 0; + virtual uint32_t getSubTypeId() const = 0; + virtual std::string getSymbolsFileName() const = 0; + virtual uint32_t getSymIndexId() const = 0; + virtual uint32_t getTargetOffset() const = 0; + virtual uint32_t getTargetRelativeVirtualAddress() const = 0; + virtual uint64_t getTargetVirtualAddress() const = 0; + virtual uint32_t getTargetSection() const = 0; + virtual uint32_t getTextureSlot() const = 0; + virtual uint32_t getTimeStamp() const = 0; + virtual uint32_t getToken() const = 0; + virtual uint32_t getTypeId() const = 0; + virtual uint32_t getUavSlot() const = 0; + virtual std::string getUndecoratedName() const = 0; + virtual uint32_t getUnmodifiedTypeId() const = 0; + virtual uint32_t getUpperBoundId() const = 0; + virtual Variant getValue() const = 0; + virtual uint32_t getVirtualBaseDispIndex() const = 0; + virtual uint32_t getVirtualBaseOffset() const = 0; + virtual uint32_t getVirtualTableShapeId() const = 0; + virtual PDB_DataKind getDataKind() const = 0; + virtual PDB_SymType getSymTag() const = 0; + virtual PDB_UniqueId getGuid() const = 0; + virtual int32_t getOffset() const = 0; + virtual int32_t getThisAdjust() const = 0; + virtual int32_t getVirtualBasePointerOffset() const = 0; + virtual PDB_LocType getLocationType() const = 0; + virtual PDB_Machine getMachineType() const = 0; + virtual PDB_ThunkOrdinal getThunkOrdinal() const = 0; + virtual uint64_t getLength() const = 0; + virtual uint64_t getLiveRangeLength() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual PDB_UdtType getUdtKind() const = 0; + virtual bool hasConstructor() const = 0; + virtual bool hasCustomCallingConvention() const = 0; + virtual bool hasFarReturn() const = 0; + virtual bool isCode() const = 0; + virtual bool isCompilerGenerated() const = 0; + virtual bool isConstType() const = 0; + virtual bool isEditAndContinueEnabled() const = 0; + virtual bool isFunction() const = 0; + virtual bool getAddressTaken() const = 0; + virtual bool getNoStackOrdering() const = 0; + virtual bool hasAlloca() const = 0; + virtual bool hasAssignmentOperator() const = 0; + virtual bool hasCTypes() const = 0; + virtual bool hasCastOperator() const = 0; + virtual bool hasDebugInfo() const = 0; + virtual bool hasEH() const = 0; + virtual bool hasEHa() const = 0; + virtual bool hasFramePointer() const = 0; + virtual bool hasInlAsm() const = 0; + virtual bool hasInlineAttribute() const = 0; + virtual bool hasInterruptReturn() const = 0; + virtual bool hasLongJump() const = 0; + virtual bool hasManagedCode() const = 0; + virtual bool hasNestedTypes() const = 0; + virtual bool hasNoInlineAttribute() const = 0; + virtual bool hasNoReturnAttribute() const = 0; + virtual bool hasOptimizedCodeDebugInfo() const = 0; + virtual bool hasOverloadedOperator() const = 0; + virtual bool hasSEH() const = 0; + virtual bool hasSecurityChecks() const = 0; + virtual bool hasSetJump() const = 0; + virtual bool hasStrictGSCheck() const = 0; + virtual bool isAcceleratorGroupSharedLocal() const = 0; + virtual bool isAcceleratorPointerTagLiveRange() const = 0; + virtual bool isAcceleratorStubFunction() const = 0; + virtual bool isAggregated() const = 0; + virtual bool isIntroVirtualFunction() const = 0; + virtual bool isCVTCIL() const = 0; + virtual bool isConstructorVirtualBase() const = 0; + virtual bool isCxxReturnUdt() const = 0; + virtual bool isDataAligned() const = 0; + virtual bool isHLSLData() const = 0; + virtual bool isHotpatchable() const = 0; + virtual bool isIndirectVirtualBaseClass() const = 0; + virtual bool isInterfaceUdt() const = 0; + virtual bool isIntrinsic() const = 0; + virtual bool isLTCG() const = 0; + virtual bool isLocationControlFlowDependent() const = 0; + virtual bool isMSILNetmodule() const = 0; + virtual bool isMatrixRowMajor() const = 0; + virtual bool isManagedCode() const = 0; + virtual bool isMSILCode() const = 0; + virtual bool isMultipleInheritance() const = 0; + virtual bool isNaked() const = 0; + virtual bool isNested() const = 0; + virtual bool isOptimizedAway() const = 0; + virtual bool isPacked() const = 0; + virtual bool isPointerBasedOnSymbolValue() const = 0; + virtual bool isPointerToDataMember() const = 0; + virtual bool isPointerToMemberFunction() const = 0; + virtual bool isPureVirtual() const = 0; + virtual bool isRValueReference() const = 0; + virtual bool isRefUdt() const = 0; + virtual bool isReference() const = 0; + virtual bool isRestrictedType() const = 0; + virtual bool isReturnValue() const = 0; + virtual bool isSafeBuffers() const = 0; + virtual bool isScoped() const = 0; + virtual bool isSdl() const = 0; + virtual bool isSingleInheritance() const = 0; + virtual bool isSplitted() const = 0; + virtual bool isStatic() const = 0; + virtual bool hasPrivateSymbols() const = 0; + virtual bool isUnalignedType() const = 0; + virtual bool isUnreached() const = 0; + virtual bool isValueUdt() const = 0; + virtual bool isVirtual() const = 0; + virtual bool isVirtualBaseClass() const = 0; + virtual bool isVirtualInheritance() const = 0; + virtual bool isVolatileType() const = 0; + virtual bool wasInlined() const = 0; + virtual std::string getUnused() const = 0; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h new file mode 100644 index 0000000..60d6f62 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -0,0 +1,56 @@ +//===- IPDBSession.h - base interface for a PDB symbol context --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSESSION_H +#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H + +#include "PDBTypes.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class PDBSymbolCompiland; +class PDBSymbolExe; + +/// IPDBSession defines an interface used to provide a context for querying +/// debug information from a debug data source (for example, a PDB). +class IPDBSession { +public: + virtual ~IPDBSession(); + + virtual uint64_t getLoadAddress() const = 0; + virtual void setLoadAddress(uint64_t Address) = 0; + virtual std::unique_ptr getGlobalScope() const = 0; + virtual std::unique_ptr getSymbolById(uint32_t SymbolId) const = 0; + + template + std::unique_ptr getConcreteSymbolById(uint32_t SymbolId) const { + auto Symbol(getSymbolById(SymbolId)); + if (!Symbol) + return nullptr; + + T *ConcreteSymbol = dyn_cast(Symbol.get()); + if (!ConcreteSymbol) + return nullptr; + Symbol.release(); + return std::unique_ptr(ConcreteSymbol); + } + + virtual std::unique_ptr getAllSourceFiles() const = 0; + virtual std::unique_ptr + getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; + virtual std::unique_ptr + getSourceFileById(uint32_t FileId) const = 0; + + virtual std::unique_ptr getDebugStreams() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h new file mode 100644 index 0000000..55000ef --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h @@ -0,0 +1,37 @@ +//===- IPDBSourceFile.h - base interface for a PDB source file --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H + +#include "PDBTypes.h" +#include +#include + +namespace llvm { + +class raw_ostream; + +/// IPDBSourceFile defines an interface used to represent source files whose +/// information are stored in the PDB. +class IPDBSourceFile { +public: + virtual ~IPDBSourceFile(); + + void dump(raw_ostream &OS, int Indent) const; + + virtual std::string getFileName() const = 0; + virtual uint32_t getUniqueId() const = 0; + virtual std::string getChecksum() const = 0; + virtual PDB_Checksum getChecksumType() const = 0; + virtual std::unique_ptr getCompilands() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h new file mode 100644 index 0000000..7193eef --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -0,0 +1,23 @@ +//===- PDB.h - base header file for creating a PDB reader -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDB_H +#define LLVM_DEBUGINFO_PDB_PDB_H + +#include "PDBTypes.h" +#include + +namespace llvm { +class StringRef; + +std::unique_ptr createPDBReader(PDB_ReaderType Type, + StringRef Path); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h new file mode 100644 index 0000000..cbbe171 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -0,0 +1,37 @@ +//===- PDBExtras.h - helper functions and classes for PDBs -------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H +#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +typedef std::unordered_map TagStats; + +raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); +raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); +raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); +raw_ostream &operator<<(raw_ostream &OS, const PDB_RegisterId &Reg); +raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); +raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang); +raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); +raw_ostream &operator<<(raw_ostream &OS, const PDB_BuiltinType &Type); +raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id); + +raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); +raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); +raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h new file mode 100644 index 0000000..dee601c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h @@ -0,0 +1,85 @@ +//===- PDBSymDumper.h - base interface for PDB symbol dumper *- C++ -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H + +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymDumper { +public: + PDBSymDumper(bool ShouldRequireImpl); + virtual ~PDBSymDumper(); + + virtual void dump(const PDBSymbolAnnotation &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolBlock &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolCompiland &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCompilandDetails &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCompilandEnv &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCustom &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolData &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolExe &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolFuncDebugEnd &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolFuncDebugStart &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolLabel &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolPublicSymbol &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolThunk &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeBaseClass &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeCustom &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeDimension &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFriend &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFunctionArg &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeManaged &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeVTable &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeVTableShape &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolUnknown &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolUsingNamespace &Symbol, raw_ostream &OS, + int Indent); + +private: + bool RequireImpl; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h new file mode 100644 index 0000000..36005eb --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -0,0 +1,98 @@ +//===- PDBSymbol.h - base class for user-facing symbol types -----*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H + +#include "ConcreteSymbolEnumerator.h" +#include "IPDBRawSymbol.h" +#include "PDBExtras.h" +#include "PDBTypes.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include + +#define FORWARD_SYMBOL_METHOD(MethodName) \ + auto MethodName() const->decltype(RawSymbol->MethodName()) { \ + return RawSymbol->MethodName(); \ + } + +namespace llvm { + +class IPDBRawSymbol; +class raw_ostream; + +#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ + static const PDB_SymType Tag = TagValue; \ + static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; } + +/// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol +/// types (e.g. functions, executables, vtables, etc). All concrete symbol +/// types inherit from PDBSymbol and expose the exact set of methods that are +/// valid for that particular symbol type, as described in the Microsoft +/// reference "Lexical and Class Hierarchy of Symbol Types": +/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx +class PDBSymbol { +protected: + PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr Symbol); + +public: + static std::unique_ptr + create(const IPDBSession &PDBSession, std::unique_ptr Symbol); + + virtual ~PDBSymbol(); + + /// Dumps the contents of a symbol a raw_ostream. By default this will just + /// call dump() on the underlying RawSymbol, which allows us to discover + /// unknown properties, but individual implementations of PDBSymbol may + /// override the behavior to only dump known fields. + virtual void dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const = 0; + void defaultDump(raw_ostream &OS, int Indent) const; + + PDB_SymType getSymTag() const; + + template std::unique_ptr findOneChild() const { + auto Enumerator(findAllChildren()); + return Enumerator->getNext(); + } + + template + std::unique_ptr> findAllChildren() const { + auto BaseIter = RawSymbol->findChildren(T::Tag); + return llvm::make_unique>(std::move(BaseIter)); + } + std::unique_ptr findAllChildren(PDB_SymType Type) const; + std::unique_ptr findAllChildren() const; + + std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const; + std::unique_ptr findChildrenByRVA(PDB_SymType Type, + StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t RVA) const; + std::unique_ptr findInlineFramesByRVA(uint32_t RVA) const; + + const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; } + IPDBRawSymbol &getRawSymbol() { return *RawSymbol; } + + const IPDBSession &getSession() const { return Session; } + + std::unique_ptr getChildStats(TagStats &Stats) const; + +protected: + const IPDBSession &Session; + const std::unique_ptr RawSymbol; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h new file mode 100644 index 0000000..347e30a --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -0,0 +1,39 @@ +//===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolAnnotation : public PDBSymbol { +public: + PDBSymbolAnnotation(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + // FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h new file mode 100644 index 0000000..a0091be --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -0,0 +1,41 @@ +//===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolBlock : public PDBSymbol { +public: + PDBSymbolBlock(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h new file mode 100644 index 0000000..055e444 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -0,0 +1,38 @@ +//===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompiland : public PDBSymbol { +public: + PDBSymbolCompiland(const IPDBSession &PDBSession, + std::unique_ptr CompilandSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLibraryName) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSourceFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h new file mode 100644 index 0000000..8836828 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -0,0 +1,55 @@ +//===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandDetails : public PDBSymbol { +public: + PDBSymbolCompilandDetails(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + void getFrontEndVersion(VersionInfo &Version) const { + RawSymbol->getFrontEndVersion(Version); + } + + void getBackEndVersion(VersionInfo &Version) const { + RawSymbol->getBackEndVersion(Version); + } + + FORWARD_SYMBOL_METHOD(getCompilerName) + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(hasDebugInfo) + FORWARD_SYMBOL_METHOD(hasManagedCode) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(isCVTCIL) + FORWARD_SYMBOL_METHOD(isDataAligned) + FORWARD_SYMBOL_METHOD(isHotpatchable) + FORWARD_SYMBOL_METHOD(isLTCG) + FORWARD_SYMBOL_METHOD(isMSILNetmodule) + FORWARD_SYMBOL_METHOD(getLanguage) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getPlatform) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h new file mode 100644 index 0000000..c3502a0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -0,0 +1,37 @@ +//===- PDBSymbolCompilandEnv.h - compiland environment variables *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandEnv : public PDBSymbol { +public: + PDBSymbolCompilandEnv(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + std::string getValue() const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h new file mode 100644 index 0000000..b433dde --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -0,0 +1,39 @@ +//===- PDBSymbolCustom.h - compiler-specific types --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class raw_ostream; + +/// PDBSymbolCustom represents symbols that are compiler-specific and do not +/// fit anywhere else in the lexical hierarchy. +/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx +class PDBSymbolCustom : public PDBSymbol { +public: + PDBSymbolCustom(const IPDBSession &PDBSession, + std::unique_ptr CustomSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + void getDataBytes(llvm::SmallVector &bytes); + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h new file mode 100644 index 0000000..8b9a657 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -0,0 +1,61 @@ +//===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolData : public PDBSymbol { +public: + PDBSymbolData(const IPDBSession &PDBSession, + std::unique_ptr DataSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) + + std::unique_ptr getType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getAddressTaken) + FORWARD_SYMBOL_METHOD(getBitPosition) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(isAggregated) + FORWARD_SYMBOL_METHOD(isSplitted) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(getRegisterId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSlot) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h new file mode 100644 index 0000000..33046f3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -0,0 +1,46 @@ +//===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolExe : public PDBSymbol { +public: + PDBSymbolExe(const IPDBSession &PDBSession, + std::unique_ptr ExeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAge) + FORWARD_SYMBOL_METHOD(getGuid) + FORWARD_SYMBOL_METHOD(hasCTypes) + FORWARD_SYMBOL_METHOD(hasPrivateSymbols) + FORWARD_SYMBOL_METHOD(getMachineType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSignature) + FORWARD_SYMBOL_METHOD(getSymbolsFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + +private: + void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType, + int Indent) const; +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h new file mode 100644 index 0000000..22ae6e0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -0,0 +1,80 @@ +//===- PDBSymbolFunc.h - class representing a function instance -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFunc : public PDBSymbol { +public: + PDBSymbolFunc(const IPDBSession &PDBSession, + std::unique_ptr FuncSymbol); + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + std::unique_ptr getSignature() const; + std::unique_ptr getClassParent() const; + std::unique_ptr> getArguments() const; + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasAlloca) + FORWARD_SYMBOL_METHOD(hasEH) + FORWARD_SYMBOL_METHOD(hasEHa) + FORWARD_SYMBOL_METHOD(hasInlAsm) + FORWARD_SYMBOL_METHOD(hasLongJump) + FORWARD_SYMBOL_METHOD(hasSEH) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(hasSetJump) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(hasInlineAttribute) + FORWARD_SYMBOL_METHOD(isNaked) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasFramePointer) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getNoStackOrdering) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getUndecoratedName) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h new file mode 100644 index 0000000..bd49314 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugEnd.h - function end bounds 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_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugEnd : public PDBSymbol { +public: + PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession, + std::unique_ptr FuncDebugEndSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h new file mode 100644 index 0000000..a62eada --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugStart.h - function start bounds 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_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugStart : public PDBSymbol { +public: + PDBSymbolFuncDebugStart(const IPDBSession &PDBSession, + std::unique_ptr FuncDebugStartSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h new file mode 100644 index 0000000..d006495 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -0,0 +1,49 @@ +//===- PDBSymbolLabel.h - label 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_DEBUGINFO_PDB_PDBSYMBOLLABEL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolLabel : public PDBSymbol { +public: + PDBSymbolLabel(const IPDBSession &PDBSession, + std::unique_ptr LabelSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h new file mode 100644 index 0000000..a8de89d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -0,0 +1,47 @@ +//===- PDBSymbolPublicSymbol.h - public symbol 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_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolPublicSymbol : public PDBSymbol { +public: + PDBSymbolPublicSymbol(const IPDBSession &PDBSession, + std::unique_ptr PublicSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(isCode) + FORWARD_SYMBOL_METHOD(isFunction) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(isManagedCode) + FORWARD_SYMBOL_METHOD(isMSILCode) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getUndecoratedName) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h new file mode 100644 index 0000000..88588f1 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -0,0 +1,57 @@ +//===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolThunk : public PDBSymbol { +public: + PDBSymbolThunk(const IPDBSession &PDBSession, + std::unique_ptr ThunkSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTargetOffset) + FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetSection) + FORWARD_SYMBOL_METHOD(getThunkOrdinal) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h new file mode 100644 index 0000000..ca925f9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -0,0 +1,45 @@ +//===- PDBSymbolTypeArray.h - array type information ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeArray : public PDBSymbol { +public: + PDBSymbolTypeArray(const IPDBSession &PDBSession, + std::unique_ptr ArrayTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) + + std::unique_ptr getElementType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getArrayIndexTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getRank) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h new file mode 100644 index 0000000..a3dcc02 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -0,0 +1,60 @@ +//===- PDBSymbolTypeBaseClass.h - base class type information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBaseClass : public PDBSymbol { +public: + PDBSymbolTypeBaseClass(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + + FORWARD_SYMBOL_METHOD(isVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex) + FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset) + // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h new file mode 100644 index 0000000..1cede08 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeBuiltin.h - builtin type information --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBuiltin : public PDBSymbol { +public: + PDBSymbolTypeBuiltin(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h new file mode 100644 index 0000000..90a043f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeCustom.h - custom compiler type information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeCustom : public PDBSymbol { +public: + PDBSymbolTypeCustom(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getOemId) + FORWARD_SYMBOL_METHOD(getOemSymbolId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h new file mode 100644 index 0000000..f871681 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeDimension.h - array dimension type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeDimension : public PDBSymbol { +public: + PDBSymbolTypeDimension(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLowerBoundId) + FORWARD_SYMBOL_METHOD(getUpperBoundId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h new file mode 100644 index 0000000..2479f46 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeEnum.h - enum type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeEnum : public PDBSymbol { +public: + PDBSymbolTypeEnum(const IPDBSession &PDBSession, + std::unique_ptr EnumTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h new file mode 100644 index 0000000..964246f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFriend.h - friend type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFriend : public PDBSymbol { +public: + PDBSymbolTypeFriend(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h new file mode 100644 index 0000000..22f1455 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFunctionArg.h - function arg type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionArg : public PDBSymbol { +public: + PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h new file mode 100644 index 0000000..82bb1fd --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -0,0 +1,50 @@ +//===- PDBSymbolTypeFunctionSig.h - function signature type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionSig : public PDBSymbol { +public: + PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) + + std::unique_ptr getReturnType() const; + std::unique_ptr getArguments() const; + std::unique_ptr getClassParent() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + void dumpArgList(raw_ostream &OS) const; + + FORWARD_SYMBOL_METHOD(getCallingConvention) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + // FORWARD_SYMBOL_METHOD(getObjectPointerType) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getThisAdjust) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h new file mode 100644 index 0000000..42f5867 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -0,0 +1,35 @@ +//===- PDBSymbolTypeManaged.h - managed type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeManaged : public PDBSymbol { +public: + PDBSymbolTypeManaged(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h new file mode 100644 index 0000000..8b2806f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -0,0 +1,43 @@ +//===- PDBSymbolTypePointer.h - pointer type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypePointer : public PDBSymbol { +public: + PDBSymbolTypePointer(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) + + std::unique_ptr getPointeeType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h new file mode 100644 index 0000000..d3a9ca2 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -0,0 +1,54 @@ +//===- PDBSymbolTypeTypedef.h - typedef type 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_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeTypedef : public PDBSymbol { +public: + PDBSymbolTypeTypedef(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h new file mode 100644 index 0000000..bf912b8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeUDT.h - UDT type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeUDT : public PDBSymbol { +public: + PDBSymbolTypeUDT(const IPDBSession &PDBSession, + std::unique_ptr UDTSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h new file mode 100644 index 0000000..6b6d99b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeVTable.h - VTable type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTable : public PDBSymbol { +public: + PDBSymbolTypeVTable(const IPDBSession &PDBSession, + std::unique_ptr VtblSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h new file mode 100644 index 0000000..e866106 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -0,0 +1,39 @@ +//===- PDBSymbolTypeVTableShape.h - VTable shape 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_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTableShape : public PDBSymbol { +public: + PDBSymbolTypeVTableShape(const IPDBSession &PDBSession, + std::unique_ptr VtblShapeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h new file mode 100644 index 0000000..7f8c6f9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -0,0 +1,34 @@ +//===- PDBSymbolUnknown.h - unknown symbol type -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H + +#include "PDBSymbol.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUnknown : public PDBSymbol { +public: + PDBSymbolUnknown(const IPDBSession &PDBSession, + std::unique_ptr UnknownSymbol); + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + static bool classof(const PDBSymbol *S) { + return (S->getSymTag() == PDB_SymType::None || + S->getSymTag() >= PDB_SymType::Max); + } +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h new file mode 100644 index 0000000..59ec16b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -0,0 +1,36 @@ +//===- PDBSymbolUsingNamespace.h - using namespace 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_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUsingNamespace : public PDBSymbol { +public: + PDBSymbolUsingNamespace(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h new file mode 100644 index 0000000..75b6475 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -0,0 +1,479 @@ +//===- PDBTypes.h - Defines enums for various fields contained in PDB ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H +#define LLVM_DEBUGINFO_PDB_PDBTYPES_H + +#include "llvm/Config/llvm-config.h" +#include +#include + +namespace llvm { + +class PDBSymDumper; +class PDBSymbol; + +class IPDBDataStream; +template class IPDBEnumChildren; +class IPDBRawSymbol; +class IPDBSession; +class IPDBSourceFile; + +typedef IPDBEnumChildren IPDBEnumSymbols; +typedef IPDBEnumChildren IPDBEnumSourceFiles; +typedef IPDBEnumChildren IPDBEnumDataStreams; + +class PDBSymbolExe; +class PDBSymbolCompiland; +class PDBSymbolCompilandDetails; +class PDBSymbolCompilandEnv; +class PDBSymbolFunc; +class PDBSymbolBlock; +class PDBSymbolData; +class PDBSymbolAnnotation; +class PDBSymbolLabel; +class PDBSymbolPublicSymbol; +class PDBSymbolTypeUDT; +class PDBSymbolTypeEnum; +class PDBSymbolTypeFunctionSig; +class PDBSymbolTypePointer; +class PDBSymbolTypeArray; +class PDBSymbolTypeBuiltin; +class PDBSymbolTypeTypedef; +class PDBSymbolTypeBaseClass; +class PDBSymbolTypeFriend; +class PDBSymbolTypeFunctionArg; +class PDBSymbolFuncDebugStart; +class PDBSymbolFuncDebugEnd; +class PDBSymbolUsingNamespace; +class PDBSymbolTypeVTableShape; +class PDBSymbolTypeVTable; +class PDBSymbolCustom; +class PDBSymbolThunk; +class PDBSymbolTypeCustom; +class PDBSymbolTypeManaged; +class PDBSymbolTypeDimension; +class PDBSymbolUnknown; + +/// Specifies which PDB reader implementation is to be used. Only a value +/// of PDB_ReaderType::DIA is supported. +enum class PDB_ReaderType { + DIA = 0, +}; + +/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but +/// is abstracted here for the purposes of non-Windows platforms that don't have +/// the GUID structure defined. +struct PDB_UniqueId { + uint64_t HighPart; + uint64_t LowPart; +}; + +/// An enumeration indicating the type of data contained in this table. +enum class PDB_TableType { + Symbols, + SourceFiles, + LineNumbers, + SectionContribs, + Segments, + InjectedSources, + FrameData +}; + +/// Defines flags used for enumerating child symbols. This corresponds to the +/// NameSearchOptions enumeration which is documented here: +/// https://msdn.microsoft.com/en-us/library/yat28ads.aspx +enum PDB_NameSearchFlags { + NS_Default = 0x0, + NS_CaseSensitive = 0x1, + NS_CaseInsensitive = 0x2, + NS_FileNameExtMatch = 0x4, + NS_Regex = 0x8, + NS_UndecoratedName = 0x10 +}; + +/// Specifies the hash algorithm that a source file from a PDB was hashed with. +/// This corresponds to the CV_SourceChksum_t enumeration and are documented +/// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx +enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 }; + +/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +enum class PDB_Cpu { + Intel8080 = 0x0, + Intel8086 = 0x1, + Intel80286 = 0x2, + Intel80386 = 0x3, + Intel80486 = 0x4, + Pentium = 0x5, + PentiumPro = 0x6, + Pentium3 = 0x7, + MIPS = 0x10, + MIPS16 = 0x11, + MIPS32 = 0x12, + MIPS64 = 0x13, + MIPSI = 0x14, + MIPSII = 0x15, + MIPSIII = 0x16, + MIPSIV = 0x17, + MIPSV = 0x18, + M68000 = 0x20, + M68010 = 0x21, + M68020 = 0x22, + M68030 = 0x23, + M68040 = 0x24, + Alpha = 0x30, + Alpha21164 = 0x31, + Alpha21164A = 0x32, + Alpha21264 = 0x33, + Alpha21364 = 0x34, + PPC601 = 0x40, + PPC603 = 0x41, + PPC604 = 0x42, + PPC620 = 0x43, + PPCFP = 0x44, + PPCBE = 0x45, + SH3 = 0x50, + SH3E = 0x51, + SH3DSP = 0x52, + SH4 = 0x53, + SHMedia = 0x54, + ARM3 = 0x60, + ARM4 = 0x61, + ARM4T = 0x62, + ARM5 = 0x63, + ARM5T = 0x64, + ARM6 = 0x65, + ARM_XMAC = 0x66, + ARM_WMMX = 0x67, + ARM7 = 0x68, + Omni = 0x70, + Ia64 = 0x80, + Ia64_2 = 0x81, + CEE = 0x90, + AM33 = 0xa0, + M32R = 0xb0, + TriCore = 0xc0, + X64 = 0xd0, + EBC = 0xe0, + Thumb = 0xf0, + ARMNT = 0xf4, + D3D11_Shader = 0x100, +}; + +enum class PDB_Machine { + Invalid = 0xffff, + Unknown = 0x0, + Am33 = 0x13, + Amd64 = 0x8664, + Arm = 0x1C0, + ArmNT = 0x1C4, + Ebc = 0xEBC, + x86 = 0x14C, + Ia64 = 0x200, + M32R = 0x9041, + Mips16 = 0x266, + MipsFpu = 0x366, + MipsFpu16 = 0x466, + PowerPC = 0x1F0, + PowerPCFP = 0x1F1, + R4000 = 0x166, + SH3 = 0x1A2, + SH3DSP = 0x1A3, + SH4 = 0x1A6, + SH5 = 0x1A8, + Thumb = 0x1C2, + WceMipsV2 = 0x169 +}; + +/// These values correspond to the CV_call_e enumeration, and are documented +/// at the following locations: +/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx +/// +enum class PDB_CallingConv { + NearCdecl = 0x00, + FarCdecl = 0x01, + NearPascal = 0x02, + FarPascal = 0x03, + NearFastcall = 0x04, + FarFastcall = 0x05, + Skipped = 0x06, + NearStdcall = 0x07, + FarStdcall = 0x08, + NearSyscall = 0x09, + FarSyscall = 0x0a, + Thiscall = 0x0b, + MipsCall = 0x0c, + Generic = 0x0d, + Alphacall = 0x0e, + Ppccall = 0x0f, + SuperHCall = 0x10, + Armcall = 0x11, + AM33call = 0x12, + Tricall = 0x13, + Sh5call = 0x14, + M32R = 0x15, + Clrcall = 0x16, + Inline = 0x17, + NearVectorcall = 0x18, + Reserved = 0x19, +}; + +/// These values correspond to the CV_CFL_LANG enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx +enum class PDB_Lang { + C = 0x00, + Cpp = 0x01, + Fortran = 0x02, + Masm = 0x03, + Pascal = 0x04, + Basic = 0x05, + Cobol = 0x06, + Link = 0x07, + Cvtres = 0x08, + Cvtpgd = 0x09, + CSharp = 0x0a, + VB = 0x0b, + ILAsm = 0x0c, + Java = 0x0d, + JScript = 0x0e, + MSIL = 0x0f, + HLSL = 0x10 +}; + +/// These values correspond to the DataKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx +enum class PDB_DataKind { + Unknown, + Local, + StaticLocal, + Param, + ObjectPtr, + FileStatic, + Global, + Member, + StaticMember, + Constant +}; + +/// These values correspond to the SymTagEnum enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx +enum class PDB_SymType { + None, + Exe, + Compiland, + CompilandDetails, + CompilandEnv, + Function, + Block, + Data, + Annotation, + Label, + PublicSymbol, + UDT, + Enum, + FunctionSig, + PointerType, + ArrayType, + BuiltinType, + Typedef, + BaseClass, + Friend, + FunctionArg, + FuncDebugStart, + FuncDebugEnd, + UsingNamespace, + VTableShape, + VTable, + Custom, + Thunk, + CustomType, + ManagedType, + Dimension, + Max +}; + +/// These values correspond to the LocationType enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx +enum class PDB_LocType { + Null, + Static, + TLS, + RegRel, + ThisRel, + Enregistered, + BitField, + Slot, + IlRel, + MetaData, + Constant, + Max +}; + +/// These values correspond to the THUNK_ORDINAL enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/dh0k8hft.aspx +enum class PDB_ThunkOrdinal { + Standard, + ThisAdjustor, + Vcall, + Pcode, + UnknownLoad, + TrampIncremental, + BranchIsland +}; + +/// These values correspond to the UdtKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx +enum class PDB_UdtType { Struct, Class, Union, Interface }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_StackFrameType { FPO, KernelTrap, KernelTSS, EBP, FrameData }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_MemoryType { Code, Data, Stack, HeapCode }; + +/// These values correspond to the Basictype enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx +enum class PDB_BuiltinType { + None = 0, + Void = 1, + Char = 2, + WCharT = 3, + Int = 6, + UInt = 7, + Float = 8, + BCD = 9, + Bool = 10, + Long = 13, + ULong = 14, + Currency = 25, + Date = 26, + Variant = 27, + Complex = 28, + Bitfield = 29, + BSTR = 30, + HResult = 31 +}; + +enum class PDB_RegisterId { + Unknown = 0, + VFrame = 30006, + AL = 1, + CL = 2, + DL = 3, + BL = 4, + AH = 5, + CH = 6, + DH = 7, + BH = 8, + AX = 9, + CX = 10, + DX = 11, + BX = 12, + SP = 13, + BP = 14, + SI = 15, + DI = 16, + EAX = 17, + ECX = 18, + EDX = 19, + EBX = 20, + ESP = 21, + EBP = 22, + ESI = 23, + EDI = 24, + ES = 25, + CS = 26, + SS = 27, + DS = 28, + FS = 29, + GS = 30, + IP = 31, + RAX = 328, + RBX = 329, + RCX = 330, + RDX = 331, + RSI = 332, + RDI = 333, + RBP = 334, + RSP = 335, + R8 = 336, + R9 = 337, + R10 = 338, + R11 = 339, + R12 = 340, + R13 = 341, + R14 = 342, + R15 = 343, +}; + +enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 }; + +struct VersionInfo { + uint32_t Major; + uint32_t Minor; + uint32_t Build; + uint32_t QFE; +}; + +enum PDB_VariantType { + Empty, + Unknown, + Int8, + Int16, + Int32, + Int64, + Single, + Double, + UInt8, + UInt16, + UInt32, + UInt64, + Bool, +}; + +struct Variant { + Variant() + : Type(PDB_VariantType::Empty) { + } + + PDB_VariantType Type; + union { + bool Bool; + int8_t Int8; + int16_t Int16; + int32_t Int32; + int64_t Int64; + float Single; + double Double; + uint8_t UInt8; + uint16_t UInt16; + uint32_t UInt32; + uint64_t UInt64; + void* Pointer; + }; +}; + +} // namespace llvm + +namespace std { +template <> struct hash { + typedef llvm::PDB_SymType argument_type; + typedef std::size_t result_type; + + result_type operator()(const argument_type &Arg) const { + return std::hash()(static_cast(Arg)); + } +}; +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index b9c0b61..17de5c7 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -138,10 +138,17 @@ protected: /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); - static ExecutionEngine *(*MCJITCtor)(std::unique_ptr M, - std::string *ErrorStr, - RTDyldMemoryManager *MCJMM, - std::unique_ptr TM); + static ExecutionEngine *(*MCJITCtor)( + std::unique_ptr M, + std::string *ErrorStr, + std::unique_ptr MCJMM, + std::unique_ptr TM); + + static ExecutionEngine *(*OrcMCJITReplacementCtor)( + std::string *ErrorStr, + std::unique_ptr OrcJMM, + std::unique_ptr TM); + static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, std::string *ErrorStr); @@ -463,6 +470,7 @@ public: } protected: + ExecutionEngine() : EEState(*this) {} explicit ExecutionEngine(std::unique_ptr M); void emitGlobals(); @@ -492,7 +500,7 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - RTDyldMemoryManager *MCJMM; + std::unique_ptr MCJMM; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; @@ -500,15 +508,20 @@ private: std::string MCPU; SmallVector MAttrs; bool VerifyModules; + bool UseOrcMCJITReplacement; /// InitEngine - Does the common initialization of default options. void InitEngine(); public: + /// Default constructor for EngineBuilder. + EngineBuilder(); + /// Constructor for EngineBuilder. - EngineBuilder(std::unique_ptr M) : M(std::move(M)) { - InitEngine(); - } + EngineBuilder(std::unique_ptr M); + + // Out-of-line since we don't have the def'n of RTDyldMemoryManager here. + ~EngineBuilder(); /// setEngineKind - Controls whether the user wants the interpreter, the JIT, /// or whichever engine works. This option defaults to EngineKind::Either. @@ -523,10 +536,7 @@ public: /// 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. - EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { - MCJMM = mcjmm; - return *this; - } + EngineBuilder &setMCJITMemoryManager(std::unique_ptr mcjmm); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. @@ -591,6 +601,11 @@ public: return *this; } + // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default. + void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { + this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; + } + TargetMachine *selectTarget(); /// selectTarget - Pick a target either via -march or by guessing the native diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index cef3aa2..c3edec8 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "RuntimeDyld.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" @@ -25,7 +26,10 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; -class ObjectImage; + +namespace object { + class ObjectFile; +} /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -57,7 +61,7 @@ public: public: JITEventListener() {} - virtual ~JITEventListener(); + virtual ~JITEventListener() {} /// NotifyObjectEmitted - Called after an object has been successfully /// emitted to memory. NotifyFunctionEmitted will not be called for @@ -67,11 +71,15 @@ public: /// The ObjectImage contains the generated object image /// with section headers updated to reflect the address at which sections /// were loaded and with relocations performed in-place on debug sections. - virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} /// NotifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + + // Get a pointe to the GDB debugger registration listener. + static JITEventListener *createGDBRegistrationListener(); #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener @@ -105,7 +113,8 @@ public: return nullptr; } #endif // USE_OPROFILE - +private: + virtual void anchor(); }; } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h deleted file mode 100644 index ee4820a..0000000 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a wrapper class to hold the memory into which an -// object will be generated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// This class acts as a container for the memory buffer used during generation -/// and loading of executable objects using MCJIT and RuntimeDyld. The -/// underlying memory for the object will be owned by the ObjectBuffer instance -/// throughout its lifetime. -class ObjectBuffer { - virtual void anchor(); -public: - ObjectBuffer() {} - ObjectBuffer(std::unique_ptr Buf) : Buffer(std::move(Buf)) {} - virtual ~ObjectBuffer() {} - - MemoryBufferRef getMemBuffer() const { return Buffer->getMemBufferRef(); } - - const char *getBufferStart() const { return Buffer->getBufferStart(); } - size_t getBufferSize() const { return Buffer->getBufferSize(); } - StringRef getBuffer() const { return Buffer->getBuffer(); } - StringRef getBufferIdentifier() const { - return Buffer->getBufferIdentifier(); - } - -protected: - // The memory contained in an ObjectBuffer - std::unique_ptr Buffer; -}; - -/// This class encapsulates the SmallVector and raw_svector_ostream needed to -/// generate an object using MC code emission while providing a common -/// ObjectBuffer interface for access to the memory once the object has been -/// generated. -class ObjectBufferStream : public ObjectBuffer { - void anchor() override; -public: - ObjectBufferStream() : OS(SV) {} - virtual ~ObjectBufferStream() {} - - raw_ostream &getOStream() { return OS; } - void flush() - { - OS.flush(); - - // Make the data accessible via the ObjectBuffer::Buffer - Buffer = - MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), "", false); - } - -protected: - SmallVector SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h deleted file mode 100644 index dc142bd..0000000 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H -#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - - -/// ObjectImage - A container class that represents an ObjectFile that has been -/// or is in the process of being loaded into memory for execution. -class ObjectImage { - ObjectImage() LLVM_DELETED_FUNCTION; - ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; - virtual void anchor(); - -protected: - std::unique_ptr Buffer; - -public: - ObjectImage(std::unique_ptr Input) : Buffer(std::move(Input)) {} - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const = 0; - virtual object::symbol_iterator end_symbols() const = 0; - iterator_range symbols() const { - return iterator_range(begin_symbols(), - end_symbols()); - } - - virtual object::section_iterator begin_sections() const = 0; - virtual object::section_iterator end_sections() const = 0; - iterator_range sections() const { - return iterator_range(begin_sections(), - end_sections()); - } - - virtual /* Triple::ArchType */ unsigned getArch() const = 0; - - // Return the name associated with this ObjectImage. - // This is usually the name of the file or MemoryBuffer that the the - // ObjectBuffer was constructed from. - StringRef getImageName() const { return Buffer->getBufferIdentifier(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; - virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; - - virtual StringRef getData() const = 0; - - virtual object::ObjectFile* getObjectFile() const = 0; - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() = 0; - virtual void deregisterWithDebugger() = 0; -}; - -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H diff --git a/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h new file mode 100644 index 0000000..b075611 --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h @@ -0,0 +1,63 @@ +//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// \brief SmallVector-backed MemoryBuffer instance. +/// +/// This class enables efficient construction of MemoryBuffers from SmallVector +/// instances. This is useful for MCJIT and Orc, where object files are streamed +/// into SmallVectors, then inspected using ObjectFile (which takes a +/// MemoryBuffer). +class ObjectMemoryBuffer : public MemoryBuffer { +public: + + /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value. + /// + /// FIXME: It'd be nice for this to be a non-templated constructor taking a + /// SmallVectorImpl here instead of a templated one taking a SmallVector, + /// but SmallVector's move-construction/assignment currently only take + /// SmallVectors. If/when that is fixed we can simplify this constructor and + /// the following one. + ObjectMemoryBuffer(SmallVectorImpl &&SV) + : SV(std::move(SV)), BufferName("") { + init(this->SV.begin(), this->SV.end(), false); + } + + /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector + /// r-value and StringRef. + ObjectMemoryBuffer(SmallVectorImpl &&SV, StringRef Name) + : SV(std::move(SV)), BufferName(Name) { + init(this->SV.begin(), this->SV.end(), false); + } + + const char* getBufferIdentifier() const override { return BufferName.c_str(); } + + BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } + +private: + SmallVector SV; + std::string BufferName; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/ExecutionEngine/Orc/CloneSubModule.h b/include/llvm/ExecutionEngine/Orc/CloneSubModule.h new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CloneSubModule.h @@ -0,0 +1,60 @@ +//===-- CloneSubModule.h - Utilities for extracting sub-modules -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for extracting sub-modules. Useful for breaking up modules +// for lazy jitting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H +#define LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include + +namespace llvm { + +class Function; +class GlobalVariable; +class Module; + +namespace orc { + +/// @brief Functor type for describing how CloneSubModule should mutate a +/// GlobalVariable. +typedef std::function HandleGlobalVariableFtor; + +/// @brief Functor type for describing how CloneSubModule should mutate a +/// Function. +typedef std::function + HandleFunctionFtor; + +/// @brief Copies the initializer from Orig to New. +/// +/// Type is suitable for implicit conversion to a HandleGlobalVariableFtor. +void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap); + +/// @brief Copies the body of Orig to New. +/// +/// Type is suitable for implicit conversion to a HandleFunctionFtor. +void copyFunctionBody(Function &New, const Function &Orig, + ValueToValueMapTy &VMap); + +/// @brief Clone a subset of the module Src into Dst. +void CloneSubModule(Module &Dst, const Module &Src, + HandleGlobalVariableFtor HandleGlobalVariable, + HandleFunctionFtor HandleFunction, bool KeepInlineAsm); + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h new file mode 100644 index 0000000..0e218e2 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -0,0 +1,355 @@ +//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// JIT layer for breaking up modules and inserting callbacks to allow +// individual functions to be compiled on demand. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H + +#include "IndirectionUtils.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Compile-on-demand layer. +/// +/// Modules added to this layer have their calls indirected, and are then +/// broken up into a set of single-function modules, each of which is added +/// to the layer below in a singleton set. The lower layer can be any layer that +/// accepts IR module sets. +/// +/// It is expected that this layer will frequently be used on top of a +/// LazyEmittingLayer. The combination of the two ensures that each function is +/// compiled only when it is first called. +template +class CompileOnDemandLayer { +public: + /// @brief Lookup helper that provides compatibility with the classic + /// static-compilation symbol resolution process. + /// + /// The CompileOnDemand (COD) layer splits modules up into multiple + /// sub-modules, each held in its own llvm::Module instance, in order to + /// support lazy compilation. When a module that contains private symbols is + /// broken up symbol linkage changes may be required to enable access to + /// "private" data that now resides in a different llvm::Module instance. To + /// retain expected symbol resolution behavior for clients of the COD layer, + /// the CODScopedLookup class uses a two-tiered lookup system to resolve + /// symbols. Lookup first scans sibling modules that were split from the same + /// original module (logical-module scoped lookup), then scans all other + /// modules that have been added to the lookup scope (logical-dylib scoped + /// lookup). + class CODScopedLookup { + private: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; + typedef std::vector SiblingHandlesList; + typedef std::list PseudoDylibModuleSetHandlesList; + + public: + /// @brief Handle for a logical module. + typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle; + + /// @brief Construct a scoped lookup. + CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + + /// @brief Start a new context for a single logical module. + LMHandle createLogicalModule() { + Handles.push_back(SiblingHandlesList()); + return std::prev(Handles.end()); + } + + /// @brief Add a concrete Module's handle to the given logical Module's + /// lookup scope. + void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) { + LMH->push_back(H); + } + + /// @brief Remove a logical Module from the CODScopedLookup entirely. + void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); } + + /// @brief Look up a symbol in this context. + JITSymbol findSymbol(LMHandle LMH, const std::string &Name) { + if (auto Symbol = findSymbolIn(LMH, Name)) + return Symbol; + + for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I) + if (I != LMH) + if (auto Symbol = findSymbolIn(I, Name)) + return Symbol; + + return nullptr; + } + + private: + + JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) { + for (auto H : *LMH) + if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false)) + return Symbol; + return nullptr; + } + + BaseLayerT &BaseLayer; + PseudoDylibModuleSetHandlesList Handles; + }; + +private: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; + typedef std::vector BaseLayerModuleSetHandleListT; + + struct ModuleSetInfo { + // Symbol lookup - just one for the whole module set. + std::shared_ptr Lookup; + + // Logical module handles. + std::vector LMHandles; + + // List of vectors of module set handles: + // One vector per logical module - each vector holds the handles for the + // exploded modules for that logical module in the base layer. + BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles; + + ModuleSetInfo(std::shared_ptr Lookup) + : Lookup(std::move(Lookup)) {} + + void releaseResources(BaseLayerT &BaseLayer) { + for (auto LMH : LMHandles) + Lookup->removeLogicalModule(LMH); + for (auto H : BaseLayerModuleSetHandles) + BaseLayer.removeModuleSet(H); + } + }; + + typedef std::list ModuleSetInfoListT; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; + + // @brief Fallback lookup functor. + typedef std::function LookupFtor; + + /// @brief Construct a compile-on-demand layer instance. + CompileOnDemandLayer(BaseLayerT &BaseLayer, LLVMContext &Context) + : BaseLayer(BaseLayer), + CompileCallbackMgr(BaseLayer, Context, 0, 64) {} + + /// @brief Add a module to the compile-on-demand layer. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + LookupFtor FallbackLookup = nullptr) { + + // If the user didn't supply a fallback lookup then just use + // getSymbolAddress. + if (!FallbackLookup) + FallbackLookup = [=](const std::string &Name) { + return findSymbol(Name, true).getAddress(); + }; + + // Create a lookup context and ModuleSetInfo for this module set. + // For the purposes of symbol resolution the set Ms will be treated as if + // the modules it contained had been linked together as a dylib. + auto DylibLookup = std::make_shared(BaseLayer); + ModuleSetHandleT H = + ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup)); + ModuleSetInfo &MSI = ModuleSetInfos.back(); + + // Process each of the modules in this module set. + for (auto &M : Ms) + partitionAndAdd(*M, MSI, FallbackLookup); + + return H; + } + + /// @brief Remove the module represented by the given handle. + /// + /// This will remove all modules in the layers below that were derived from + /// the module represented by H. + void removeModuleSet(ModuleSetHandleT H) { + H->releaseResources(BaseLayer); + ModuleSetInfos.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of a symbol provided by this layer, or some layer + /// below this one. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second; + for (auto &BH : BaseLayerHandles) { + if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly)) + return Symbol; + } + return nullptr; + } + +private: + + void partitionAndAdd(Module &M, ModuleSetInfo &MSI, + LookupFtor FallbackLookup) { + const char *AddrSuffix = "$orc_addr"; + const char *BodySuffix = "$orc_body"; + + // We're going to break M up into a bunch of sub-modules, but we want + // internal linkage symbols to still resolve sensibly. CODScopedLookup + // provides the "logical module" concept to make this work, so create a + // new logical module for M. + auto DylibLookup = MSI.Lookup; + auto LogicalModule = DylibLookup->createLogicalModule(); + MSI.LMHandles.push_back(LogicalModule); + + // Partition M into a "globals and stubs" module, a "common symbols" module, + // and a list of single-function modules. + auto PartitionedModule = fullyPartition(M); + auto StubsModule = std::move(PartitionedModule.GlobalVars); + auto CommonsModule = std::move(PartitionedModule.Commons); + auto FunctionModules = std::move(PartitionedModule.Functions); + + // Emit the commons stright away. + auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule, + FallbackLookup); + BaseLayer.emitAndFinalize(CommonHandle); + + // Map of definition names to callback-info data structures. We'll use + // this to build the compile actions for the stubs below. + typedef std::map + StubInfoMap; + StubInfoMap StubInfos; + + // Now we need to take each of the extracted Modules and add them to + // base layer. Each Module will be added individually to make sure they + // can be compiled separately, and each will get its own lookaside + // memory manager that will resolve within this logical module first. + for (auto &SubM : FunctionModules) { + + // Keep track of the stubs we create for this module so that we can set + // their compile actions. + std::vector NewStubInfos; + + // Search for function definitions and insert stubs into the stubs + // module. + for (auto &F : *SubM) { + if (F.isDeclaration()) + continue; + + std::string Name = F.getName(); + Function *Proto = StubsModule->getFunction(Name); + assert(Proto && "Failed to clone function decl into stubs module."); + auto CallbackInfo = + CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType()); + GlobalVariable *FunctionBodyPointer = + createImplPointer(*Proto, Name + AddrSuffix, + CallbackInfo.getAddress()); + makeStub(*Proto, *FunctionBodyPointer); + + F.setName(Name + BodySuffix); + F.setVisibility(GlobalValue::HiddenVisibility); + + auto KV = std::make_pair(std::move(Name), std::move(CallbackInfo)); + NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV)); + } + + auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup); + + // Set the compile actions for this module: + for (auto &KVPair : NewStubInfos) { + std::string BodyName = Mangle(KVPair->first + BodySuffix, + *M.getDataLayout()); + auto &CCInfo = KVPair->second; + CCInfo.setCompileAction( + [=](){ + return BaseLayer.findSymbolIn(H, BodyName, false).getAddress(); + }); + } + + } + + // Ok - we've processed all the partitioned modules. Now add the + // stubs/globals module and set the update actions. + auto StubsH = + addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup); + + for (auto &KVPair : StubInfos) { + std::string AddrName = Mangle(KVPair.first + AddrSuffix, + *M.getDataLayout()); + auto &CCInfo = KVPair.second; + CCInfo.setUpdateAction( + CompileCallbackMgr.getLocalFPUpdater(StubsH, AddrName)); + } + } + + // Add the given Module to the base layer using a memory manager that will + // perform the appropriate scoped lookup (i.e. will look first with in the + // module from which it was extracted, then into the set to which that module + // belonged, and finally externally). + BaseLayerModuleSetHandleT addModule( + std::unique_ptr M, + ModuleSetInfo &MSI, + typename CODScopedLookup::LMHandle LogicalModule, + LookupFtor FallbackLookup) { + + // Add this module to the JIT with a memory manager that uses the + // DylibLookup to resolve symbols. + std::vector> MSet; + MSet.push_back(std::move(M)); + + auto DylibLookup = MSI.Lookup; + auto MM = + createLookasideRTDyldMM( + [=](const std::string &Name) { + if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) + return Symbol.getAddress(); + return FallbackLookup(Name); + }, + [=](const std::string &Name) { + return DylibLookup->findSymbol(LogicalModule, Name).getAddress(); + }); + + BaseLayerModuleSetHandleT H = + BaseLayer.addModuleSet(std::move(MSet), std::move(MM)); + // Add this module to the logical module lookup. + DylibLookup->addToLogicalModule(LogicalModule, H); + MSI.BaseLayerModuleSetHandles.push_back(H); + + return H; + } + + static std::string Mangle(StringRef Name, const DataLayout &DL) { + Mangler M(&DL); + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + M.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + BaseLayerT &BaseLayer; + CompileCallbackMgrT CompileCallbackMgr; + ModuleSetInfoListT ModuleSetInfos; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h new file mode 100644 index 0000000..49a1fba --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -0,0 +1,62 @@ +//===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for compiling IR to object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H + +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +namespace orc { + +/// @brief Simple compile functor: Takes a single IR module and returns an +/// ObjectFile. +class SimpleCompiler { +public: + /// @brief Construct a simple compile functor with the given target. + SimpleCompiler(TargetMachine &TM) : TM(TM) {} + + /// @brief Compile a Module to an ObjectFile. + object::OwningBinary operator()(Module &M) const { + SmallVector ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); + + legacy::PassManager PM; + MCContext *Ctx; + if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + PM.run(M); + ObjStream.flush(); + std::unique_ptr ObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); + ErrorOr> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + // TODO: Actually report errors helpfully. + typedef object::OwningBinary OwningObj; + if (Obj) + return OwningObj(std::move(*Obj), std::move(ObjBuffer)); + return OwningObj(nullptr, nullptr); + } + +private: + TargetMachine &TM; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h new file mode 100644 index 0000000..6a47622 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -0,0 +1,146 @@ +//===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a basic, eagerly compiling layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H + +#include "JITSymbol.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Object/ObjectFile.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Eager IR compiling layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately compiles each IR module to an object file (each IR Module is +/// compiled separately). The resulting set of object files is then added to +/// the layer below, which must implement the object layer concept. +template class IRCompileLayer { +public: + typedef std::function(Module &)> + CompileFtor; + +private: + typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT; + + typedef std::vector> OwningObjectVec; + typedef std::vector> OwningBufferVec; + +public: + /// @brief Handle to a set of compiled modules. + typedef ObjSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRCompileLayer with the given BaseLayer, which must + /// implement the ObjectLayer concept. + IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile) + : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {} + + /// @brief Set an ObjectCache to query before compiling. + void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } + + /// @brief Compile each module in the given module set, then then add the + /// resulting set of objects to the base layer, along with the memory + // manager MM. + /// + /// @return A handle for the added modules. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + std::unique_ptr MM) { + OwningObjectVec Objects; + OwningBufferVec Buffers; + + for (const auto &M : Ms) { + std::unique_ptr Object; + std::unique_ptr Buffer; + + if (ObjCache) + std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary(); + + if (!Object) { + std::tie(Object, Buffer) = Compile(*M).takeBinary(); + if (ObjCache) + ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef()); + } + + Objects.push_back(std::move(Object)); + Buffers.push_back(std::move(Buffer)); + } + + ModuleSetHandleT H = + BaseLayer.addObjectSet(Objects, std::move(MM)); + + BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers)); + + return H; + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. This call is + /// forwarded to the base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + +private: + object::OwningBinary + tryToLoadFromObjectCache(const Module &M) { + std::unique_ptr ObjBuffer = ObjCache->getObject(&M); + if (!ObjBuffer) + return object::OwningBinary(); + + ErrorOr> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (!Obj) + return object::OwningBinary(); + + return object::OwningBinary(std::move(*Obj), + std::move(ObjBuffer)); + } + + BaseLayerT &BaseLayer; + CompileFtor Compile; + ObjectCache *ObjCache; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h new file mode 100644 index 0000000..e9d3d34 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -0,0 +1,246 @@ +//===-- IndirectionUtils.h - Utilities for adding indirections --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for adding indirections and breaking up modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H + +#include "JITSymbol.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Base class for JITLayer independent aspects of +/// JITCompileCallbackManager. +template +class JITCompileCallbackManagerBase { +public: + + /// @brief Construct a JITCompileCallbackManagerBase. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no + /// available trampoline when getCompileCallback is + /// called. + JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : ErrorHandlerAddress(ErrorHandlerAddress), + NumTrampolinesPerBlock(NumTrampolinesPerBlock) {} + + /// @brief Execute the callback for the given trampoline id. Called by the JIT + /// to compile functions on demand. + TargetAddress executeCompileCallback(TargetAddress TrampolineID) { + typename TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID); + // FIXME: Also raise an error in the Orc error-handler when we finally have + // one. + if (I == ActiveTrampolines.end()) + return ErrorHandlerAddress; + + // Found a callback handler. Yank this trampoline out of the active list and + // put it back in the available trampolines list, then try to run the + // handler's compile and update actions. + // Moving the trampoline ID back to the available list first means there's at + // least one available trampoline if the compile action triggers a request for + // a new one. + AvailableTrampolines.push_back(I->first - TargetT::CallSize); + auto CallbackHandler = std::move(I->second); + ActiveTrampolines.erase(I); + + if (auto Addr = CallbackHandler.Compile()) { + CallbackHandler.Update(Addr); + return Addr; + } + return ErrorHandlerAddress; + } + +protected: + + typedef std::function CompileFtorT; + typedef std::function UpdateFtorT; + + struct CallbackHandler { + CompileFtorT Compile; + UpdateFtorT Update; + }; + + TargetAddress ErrorHandlerAddress; + unsigned NumTrampolinesPerBlock; + + typedef std::map TrampolineMapT; + TrampolineMapT ActiveTrampolines; + std::vector AvailableTrampolines; +}; + +/// @brief Manage compile callbacks. +template +class JITCompileCallbackManager : + public JITCompileCallbackManagerBase { +public: + + typedef typename JITCompileCallbackManagerBase::CompileFtorT + CompileFtorT; + typedef typename JITCompileCallbackManagerBase::UpdateFtorT + UpdateFtorT; + + /// @brief Construct a JITCompileCallbackManager. + /// @param JIT JIT layer to emit callback trampolines, etc. into. + /// @param Context LLVMContext to use for trampoline & resolve block modules. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever + /// there is no existing callback trampoline. + /// (Trampolines are allocated in blocks for + /// efficiency.) + JITCompileCallbackManager(JITLayerT &JIT, LLVMContext &Context, + TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : JITCompileCallbackManagerBase(ErrorHandlerAddress, + NumTrampolinesPerBlock), + JIT(JIT) { + emitResolverBlock(Context); + } + + /// @brief Handle to a newly created compile callback. Can be used to get an + /// IR constant representing the address of the trampoline, and to set + /// the compile and update actions for the callback. + class CompileCallbackInfo { + public: + CompileCallbackInfo(Constant *Addr, CompileFtorT &Compile, + UpdateFtorT &Update) + : Addr(Addr), Compile(Compile), Update(Update) {} + + Constant* getAddress() const { return Addr; } + void setCompileAction(CompileFtorT Compile) { + this->Compile = std::move(Compile); + } + void setUpdateAction(UpdateFtorT Update) { + this->Update = std::move(Update); + } + private: + Constant *Addr; + CompileFtorT &Compile; + UpdateFtorT &Update; + }; + + /// @brief Get/create a compile callback with the given signature. + CompileCallbackInfo getCompileCallback(FunctionType &FT) { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext()); + auto &CallbackHandler = + this->ActiveTrampolines[TrampolineAddr + TargetT::CallSize]; + Constant *AddrIntVal = + ConstantInt::get(Type::getInt64Ty(FT.getContext()), TrampolineAddr); + Constant *AddrPtrVal = + ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal, + PointerType::get(&FT, 0)); + + return CompileCallbackInfo(AddrPtrVal, CallbackHandler.Compile, + CallbackHandler.Update); + } + + /// @brief Get a functor for updating the value of a named function pointer. + UpdateFtorT getLocalFPUpdater(typename JITLayerT::ModuleSetHandleT H, + std::string Name) { + // FIXME: Move-capture Name once we can use C++14. + return [=](TargetAddress Addr) { + auto FPSym = JIT.findSymbolIn(H, Name, true); + assert(FPSym && "Cannot find function pointer to update."); + void *FPAddr = reinterpret_cast( + static_cast(FPSym.getAddress())); + memcpy(FPAddr, &Addr, sizeof(uintptr_t)); + }; + } + +private: + + std::vector> + SingletonSet(std::unique_ptr M) { + std::vector> Ms; + Ms.push_back(std::move(M)); + return Ms; + } + + void emitResolverBlock(LLVMContext &Context) { + std::unique_ptr M(new Module("resolver_block_module", + Context)); + TargetT::insertResolverBlock(*M, *this); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + JIT.emitAndFinalize(H); + auto ResolverBlockSymbol = + JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); + assert(ResolverBlockSymbol && "Failed to insert resolver block"); + ResolverBlockAddr = ResolverBlockSymbol.getAddress(); + } + + TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) { + if (this->AvailableTrampolines.empty()) + grow(Context); + assert(!this->AvailableTrampolines.empty() && + "Failed to grow available trampolines."); + TargetAddress TrampolineAddr = this->AvailableTrampolines.back(); + this->AvailableTrampolines.pop_back(); + return TrampolineAddr; + } + + void grow(LLVMContext &Context) { + assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); + std::unique_ptr M(new Module("trampoline_block", Context)); + auto GetLabelName = + TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, + this->NumTrampolinesPerBlock, + this->ActiveTrampolines.size()); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + JIT.emitAndFinalize(H); + for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { + std::string Name = GetLabelName(I); + auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false); + assert(TrampolineSymbol && "Failed to emit trampoline."); + this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress()); + } + } + + JITLayerT &JIT; + TargetAddress ResolverBlockAddr; +}; + +GlobalVariable* createImplPointer(Function &F, const Twine &Name, + Constant *Initializer); + +void makeStub(Function &F, GlobalVariable &ImplPointer); + +typedef std::map> ModulePartitionMap; + +void partition(Module &M, const ModulePartitionMap &PMap); + +/// @brief Struct for trivial "complete" partitioning of a module. +class FullyPartitionedModule { +public: + std::unique_ptr GlobalVars; + std::unique_ptr Commons; + std::vector> Functions; + + FullyPartitionedModule() = default; + FullyPartitionedModule(FullyPartitionedModule &&S) + : GlobalVars(std::move(S.GlobalVars)), Commons(std::move(S.Commons)), + Functions(std::move(S.Functions)) {} +}; + +FullyPartitionedModule fullyPartition(Module &M); + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h new file mode 100644 index 0000000..a670222 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -0,0 +1,74 @@ +//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstraction for target process addresses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H +#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H + +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { +namespace orc { + +/// @brief Represents an address in the target process's address space. +typedef uint64_t TargetAddress; + +/// @brief Represents a symbol in the JIT. +class JITSymbol { +public: + typedef std::function GetAddressFtor; + + /// @brief Create a 'null' symbol that represents failure to find a symbol + /// definition. + JITSymbol(std::nullptr_t) : CachedAddr(0) {} + + /// @brief Create a symbol for a definition with a known address. + JITSymbol(TargetAddress Addr) + : CachedAddr(Addr) {} + + /// @brief Create a symbol for a definition that doesn't have a known address + /// yet. + /// @param GetAddress A functor to materialize a definition (fixing the + /// address) on demand. + /// + /// This constructor allows a JIT layer to provide a reference to a symbol + /// definition without actually materializing the definition up front. The + /// user can materialize the definition at any time by calling the getAddress + /// method. + JITSymbol(GetAddressFtor GetAddress) + : CachedAddr(0), GetAddress(std::move(GetAddress)) {} + + /// @brief Returns true if the symbol exists, false otherwise. + explicit operator bool() const { return CachedAddr || GetAddress; } + + /// @brief Get the address of the symbol in the target address space. Returns + /// '0' if the symbol does not exist. + TargetAddress getAddress() { + if (GetAddress) { + CachedAddr = GetAddress(); + assert(CachedAddr && "Symbol could not be materialized."); + GetAddress = nullptr; + } + return CachedAddr; + } + +private: + TargetAddress CachedAddr; + GetAddressFtor GetAddress; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h new file mode 100644 index 0000000..2a94abe --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -0,0 +1,283 @@ +//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a lazy-emitting layer for the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H + +#include "JITSymbol.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/ADT/StringMap.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Lazy-emitting IR layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does +/// not immediately emit them the layer below. Instead, emissing to the base +/// layer is deferred until the first time the client requests the address +/// (via JITSymbol::getAddress) for a symbol contained in this layer. +template class LazyEmittingLayer { +public: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT; + +private: + class EmissionDeferredSet { + public: + EmissionDeferredSet() : EmitState(NotEmitted) {} + virtual ~EmissionDeferredSet() {} + + JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { + switch (EmitState) { + case NotEmitted: + if (provides(Name, ExportedSymbolsOnly)) { + // Create a std::string version of Name to capture here - the argument + // (a StringRef) may go away before the lambda is executed. + // FIXME: Use capture-init when we move to C++14. + std::string PName = Name; + return JITSymbol( + [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress { + if (this->EmitState == Emitting) + return 0; + else if (this->EmitState == NotEmitted) { + this->EmitState = Emitting; + Handle = this->emitToBaseLayer(B); + this->EmitState = Emitted; + } + return B.findSymbolIn(Handle, PName, ExportedSymbolsOnly) + .getAddress(); + }); + } else + return nullptr; + case Emitting: + // Calling "emit" can trigger external symbol lookup (e.g. to check for + // pre-existing definitions of common-symbol), but it will never find in + // this module that it would not have found already, so return null from + // here. + return nullptr; + case Emitted: + return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + } + llvm_unreachable("Invalid emit-state."); + } + + void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { + if (EmitState != NotEmitted) + BaseLayer.removeModuleSet(Handle); + } + + void emitAndFinalize(BaseLayerT &BaseLayer) { + assert(EmitState != Emitting && + "Cannot emitAndFinalize while already emitting"); + if (EmitState == NotEmitted) { + EmitState = Emitting; + Handle = emitToBaseLayer(BaseLayer); + EmitState = Emitted; + } + BaseLayer.emitAndFinalize(Handle); + } + + template + static std::unique_ptr + create(BaseLayerT &B, ModuleSetT Ms, + std::unique_ptr MM); + + protected: + virtual bool provides(StringRef Name, bool ExportedSymbolsOnly) const = 0; + virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0; + + private: + enum { NotEmitted, Emitting, Emitted } EmitState; + BaseLayerHandleT Handle; + }; + + template + class EmissionDeferredSetImpl : public EmissionDeferredSet { + public: + EmissionDeferredSetImpl(ModuleSetT Ms, + std::unique_ptr MM) + : Ms(std::move(Ms)), MM(std::move(MM)) {} + + protected: + + BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override { + // We don't need the mangled names set any more: Once we've emitted this + // to the base layer we'll just look for symbols there. + MangledNames.reset(); + return BaseLayer.addModuleSet(std::move(Ms), std::move(MM)); + } + + bool provides(StringRef Name, bool ExportedSymbolsOnly) const override { + // FIXME: We could clean all this up if we had a way to reliably demangle + // names: We could just demangle name and search, rather than + // mangling everything else. + + // If we have already built the mangled name set then just search it. + if (MangledNames) { + auto VI = MangledNames->find(Name); + if (VI == MangledNames->end()) + return false; + return !ExportedSymbolsOnly || VI->second; + } + + // If we haven't built the mangled name set yet, try to build it. As an + // optimization this will leave MangledNames set to nullptr if we find + // Name in the process of building the set. + buildMangledNames(Name, ExportedSymbolsOnly); + if (!MangledNames) + return true; + return false; + } + + private: + // If the mangled name of the given GlobalValue matches the given search + // name (and its visibility conforms to the ExportedSymbolsOnly flag) then + // just return 'true'. Otherwise, add the mangled name to the Names map and + // return 'false'. + bool addGlobalValue(StringMap &Names, const GlobalValue &GV, + const Mangler &Mang, StringRef SearchName, + bool ExportedSymbolsOnly) const { + // Modules don't "provide" decls or common symbols. + if (GV.isDeclaration() || GV.hasCommonLinkage()) + return false; + + // Mangle the GV name. + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, &GV, false); + } + + // Check whether this is the name we were searching for, and if it is then + // bail out early. + if (MangledName == SearchName) + if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) + return true; + + // Otherwise add this to the map for later. + Names[MangledName] = GV.hasDefaultVisibility(); + return false; + } + + // Build the MangledNames map. Bails out early (with MangledNames left set + // to nullptr) if the given SearchName is found while building the map. + void buildMangledNames(StringRef SearchName, + bool ExportedSymbolsOnly) const { + assert(!MangledNames && "Mangled names map already exists?"); + + auto Names = llvm::make_unique>(); + + for (const auto &M : Ms) { + Mangler Mang(M->getDataLayout()); + + for (const auto &GV : M->globals()) + if (addGlobalValue(*Names, GV, Mang, SearchName, ExportedSymbolsOnly)) + return; + + for (const auto &F : *M) + if (addGlobalValue(*Names, F, Mang, SearchName, ExportedSymbolsOnly)) + return; + } + + MangledNames = std::move(Names); + } + + ModuleSetT Ms; + std::unique_ptr MM; + mutable std::unique_ptr> MangledNames; + }; + + typedef std::list> ModuleSetListT; + + BaseLayerT &BaseLayer; + ModuleSetListT ModuleSetList; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename ModuleSetListT::iterator ModuleSetHandleT; + + /// @brief Construct a lazy emitting layer. + LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + + /// @brief Add the given set of modules to the lazy emitting layer. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + std::unique_ptr MM) { + return ModuleSetList.insert( + ModuleSetList.end(), + EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM))); + } + + /// @brief Remove the module set represented by the given handle. + /// + /// This method will free the memory associated with the given module set, + /// both in this layer, and the base layer. + void removeModuleSet(ModuleSetHandleT H) { + (*H)->removeModulesFromBaseLayer(BaseLayer); + ModuleSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + // Look for the symbol among existing definitions. + if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) + return Symbol; + + // If not found then search the deferred sets. If any of these contain a + // definition of 'Name' then they will return a JITSymbol that will emit + // the corresponding module when the symbol address is requested. + for (auto &DeferredSet : ModuleSetList) + if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer)) + return Symbol; + + // If no definition found anywhere return a null symbol. + return nullptr; + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + (*H)->emitAndFinalize(BaseLayer); + } + +}; + +template +template +std::unique_ptr::EmissionDeferredSet> +LazyEmittingLayer::EmissionDeferredSet::create( + BaseLayerT &B, ModuleSetT Ms, std::unique_ptr MM) { + return llvm::make_unique>(std::move(Ms), + std::move(MM)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h new file mode 100644 index 0000000..4456404 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h @@ -0,0 +1,92 @@ +//===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines an adapter for RuntimeDyldMM that allows lookups for external +// symbols to go via a functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H +#define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H + +#include "llvm/ADT/STLExtras.h" +#include +#include + +namespace llvm { +namespace orc { + +/// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external +/// symbols to go via a functor, before falling back to the lookup logic +/// provided by the underlying RuntimeDyldMM instance. +/// +/// This class is useful for redirecting symbol lookup back to various layers +/// of a JIT component stack, e.g. to enable lazy module emission. +/// +template +class LookasideRTDyldMM : public BaseRTDyldMM { +public: + /// @brief Create a LookasideRTDyldMM intance. + LookasideRTDyldMM(ExternalLookupFtor ExternalLookup, + DylibLookupFtor DylibLookup) + : ExternalLookup(std::move(ExternalLookup)), + DylibLookup(std::move(DylibLookup)) {} + + /// @brief Look up the given symbol address, first via the functor this + /// instance was created with, then (if the symbol isn't found) + /// via the underlying RuntimeDyldMM. + uint64_t getSymbolAddress(const std::string &Name) override { + if (uint64_t Addr = ExternalLookup(Name)) + return Addr; + return BaseRTDyldMM::getSymbolAddress(Name); + } + + uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override { + if (uint64_t Addr = DylibLookup(Name)) + return Addr; + return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name); + }; + + /// @brief Get a reference to the ExternalLookup functor. + ExternalLookupFtor &getExternalLookup() { return ExternalLookup; } + + /// @brief Get a const-reference to the ExternalLookup functor. + const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; } + + /// @brief Get a reference to the DylibLookup functor. + DylibLookupFtor &getDylibLookup() { return DylibLookup; } + + /// @brief Get a const-reference to the DylibLookup functor. + const DylibLookupFtor &getDylibLookup() const { return DylibLookup; } + +private: + ExternalLookupFtor ExternalLookup; + DylibLookupFtor DylibLookup; +}; + +/// @brief Create a LookasideRTDyldMM from a base memory manager type, an +/// external lookup functor, and a dylib lookup functor. +template +std::unique_ptr< + LookasideRTDyldMM> +createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup, + DylibLookupFtor &&DylibLookup) { + typedef LookasideRTDyldMM + ThisLookasideMM; + return llvm::make_unique( + std::forward(ExternalLookup), + std::forward(DylibLookup)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h new file mode 100644 index 0000000..36af0fe --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -0,0 +1,267 @@ +//===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for the object layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H + +#include "JITSymbol.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include +#include + +namespace llvm { +namespace orc { + +class ObjectLinkingLayerBase { +protected: + + /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT. + /// + /// An instance of this class will be created for each set of objects added + /// via JITObjectLayer::addObjectSet. Deleting the instance (via + /// removeObjectSet) frees its memory, removing all symbol definitions that + /// had been provided by this instance. Higher level layers are responsible + /// for taking any action required to handle the missing symbols. + class LinkedObjectSet { + LinkedObjectSet(const LinkedObjectSet&) = delete; + void operator=(const LinkedObjectSet&) = delete; + public: + LinkedObjectSet(std::unique_ptr MM) + : MM(std::move(MM)), RTDyld(llvm::make_unique(&*this->MM)), + State(Raw) {} + + // MSVC 2012 cannot infer a move constructor, so write it out longhand. + LinkedObjectSet(LinkedObjectSet &&O) + : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {} + + std::unique_ptr + addObject(const object::ObjectFile &Obj) { + return RTDyld->loadObject(Obj); + } + + TargetAddress getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) { + if (ExportedSymbolsOnly) + return RTDyld->getExportedSymbolLoadAddress(Name); + return RTDyld->getSymbolLoadAddress(Name); + } + + bool NeedsFinalization() const { return (State == Raw); } + + void Finalize() { + State = Finalizing; + RTDyld->resolveRelocations(); + RTDyld->registerEHFrames(); + MM->finalizeMemory(); + OwnedBuffers.clear(); + State = Finalized; + } + + void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) { + assert((State != Finalized) && + "Attempting to remap sections for finalized objects."); + RTDyld->mapSectionAddress(LocalAddress, TargetAddr); + } + + void takeOwnershipOfBuffer(std::unique_ptr B) { + OwnedBuffers.push_back(std::move(B)); + } + + private: + std::unique_ptr MM; + std::unique_ptr RTDyld; + enum { Raw, Finalizing, Finalized } State; + + // FIXME: This ownership hack only exists because RuntimeDyldELF still + // wants to be able to inspect the original object when resolving + // relocations. As soon as that can be fixed this should be removed. + std::vector> OwnedBuffers; + }; + + typedef std::list LinkedObjectSetListT; + +public: + /// @brief Handle to a set of loaded objects. + typedef LinkedObjectSetListT::iterator ObjSetHandleT; + + // Ownership hack. + // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without + // referencing the original object. + template + void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { + for (auto &MB : MBs) + H->takeOwnershipOfBuffer(std::move(MB)); + } + +}; + +/// @brief Default (no-op) action to perform when loading objects. +class DoNothingOnNotifyLoaded { +public: + template + void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &, + const LoadResult &) {} +}; + +/// @brief Bare bones object linking layer. +/// +/// This class is intended to be used as the base layer for a JIT. It allows +/// object files to be loaded into memory, linked, and the addresses of their +/// symbols queried. All objects added to this layer can see each other's +/// symbols. +template +class ObjectLinkingLayer : public ObjectLinkingLayerBase { +public: + + /// @brief LoadedObjectInfo list. Contains a list of owning pointers to + /// RuntimeDyld::LoadedObjectInfo instances. + typedef std::vector> + LoadedObjInfoList; + + /// @brief Functor to create RTDyldMemoryManager instances. + typedef std::function()> CreateRTDyldMMFtor; + + /// @brief Functor for receiving finalization notifications. + typedef std::function NotifyFinalizedFtor; + + /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// NotifyFinalized and CreateMemoryManager functors. + ObjectLinkingLayer( + CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(), + NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) + : NotifyLoaded(std::move(NotifyLoaded)), + NotifyFinalized(std::move(NotifyFinalized)), + CreateMemoryManager(std::move(CreateMemoryManager)) {} + + /// @brief Add a set of objects (or archives) that will be treated as a unit + /// for the purposes of symbol lookup and memory management. + /// + /// @return A pair containing (1) A handle that can be used to free the memory + /// allocated for the objects, and (2) a LoadedObjInfoList containing + /// one LoadedObjInfo instance for each object at the corresponding + /// index in the Objects list. + /// + /// This version of this method allows the client to pass in an + /// RTDyldMemoryManager instance that will be used to allocate memory and look + /// up external symbol addresses for the given objects. + template + ObjSetHandleT addObjectSet(const ObjSetT &Objects, + std::unique_ptr MM) { + + if (!MM) { + assert(CreateMemoryManager && + "No memory manager or memory manager creator provided."); + MM = CreateMemoryManager(); + } + + ObjSetHandleT Handle = LinkedObjSetList.insert( + LinkedObjSetList.end(), LinkedObjectSet(std::move(MM))); + LinkedObjectSet &LOS = *Handle; + LoadedObjInfoList LoadedObjInfos; + + for (auto &Obj : Objects) + LoadedObjInfos.push_back(LOS.addObject(*Obj)); + + NotifyLoaded(Handle, Objects, LoadedObjInfos); + + return Handle; + } + + /// @brief Remove the set of objects associated with handle H. + /// + /// All memory allocated for the objects will be freed, and the sections and + /// symbols they provided will no longer be available. No attempt is made to + /// re-emit the missing symbols, and any use of these symbols (directly or + /// indirectly) will result in undefined behavior. If dependence tracking is + /// required to detect or resolve such issues it should be added at a higher + /// layer. + void removeObjectSet(ObjSetHandleT H) { + // How do we invalidate the symbols in H? + LinkedObjSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E; + ++I) + if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) + return Symbol; + + return nullptr; + } + + /// @brief Search for the given named symbol in the context of the set of + /// loaded objects represented by the handle H. + /// @param H The handle for the object set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given object set. + JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, + bool ExportedSymbolsOnly) { + if (auto Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) { + if (!H->NeedsFinalization()) { + // If this instance has already been finalized then we can just return + // the address. + return JITSymbol(Addr); + } else { + // If this instance needs finalization return a functor that will do it. + // The functor still needs to double-check whether finalization is + // required, in case someone else finalizes this set before the functor + // is called. + return JITSymbol( + [this, Addr, H]() { + if (H->NeedsFinalization()) { + H->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + return Addr; + }); + } + } + + return nullptr; + } + + /// @brief Map section addresses for the objects associated with the handle H. + void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + H->mapSectionAddress(LocalAddress, TargetAddr); + } + + /// @brief Immediately emit and finalize the object set represented by the + /// given handle. + /// @param H Handle for object set to emit/finalize. + void emitAndFinalize(ObjSetHandleT H) { + H->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + +private: + LinkedObjectSetListT LinkedObjSetList; + NotifyLoadedFtor NotifyLoaded; + NotifyFinalizedFtor NotifyFinalized; + CreateRTDyldMMFtor CreateMemoryManager; +}; + +} // End namespace orc. +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h new file mode 100644 index 0000000..c6f866a --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h @@ -0,0 +1,56 @@ +//===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Target specific code for Orc, e.g. callback assembly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H +#define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H + +#include "IndirectionUtils.h" + +namespace llvm { +namespace orc { + +class OrcX86_64 { +public: + static const char *ResolverBlockName; + + /// @brief Insert module-level inline callback asm into module M for the + /// symbols managed by JITResolveCallbackHandler J. + static void insertResolverBlock( + Module &M, + JITCompileCallbackManagerBase &JCBM); + + /// @brief Get a label name from the given index. + typedef std::function LabelNameFtor; + + static const unsigned CallSize = 6; + + /// @brief Insert the requested number of trampolines into the given module. + /// @param M Module to insert the call block into. + /// @param NumCalls Number of calls to create in the call block. + /// @param StartIndex Optional argument specifying the index suffix to start + /// with. + /// @return A functor that provides the symbol name for each entry in the call + /// block. + /// + static LabelNameFtor insertCompileCallbackTrampolines( + Module &M, + TargetAddress TrampolineAddr, + unsigned NumCalls, + unsigned StartIndex = 0); + +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H diff --git a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h new file mode 100644 index 0000000..4cd5648 --- /dev/null +++ b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h @@ -0,0 +1,38 @@ +//===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces OrcMCJITReplacement to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H +#define LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInOrcMCJITReplacement(); + +namespace { + struct ForceOrcMCJITReplacementLinking { + ForceOrcMCJITReplacementLinking() { + // We must reference OrcMCJITReplacement in such a way that compilers will + // not delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough to know + // that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInOrcMCJITReplacement(); + } + } ForceOrcMCJITReplacementLinking; +} + +#endif diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index b941efc..792a499 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -22,7 +22,10 @@ namespace llvm { class ExecutionEngine; -class ObjectImage; + + namespace object { + class ObjectFile; + } // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of @@ -31,8 +34,8 @@ class ObjectImage; // 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; + RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; + void operator=(const RTDyldMemoryManager&) = delete; public: RTDyldMemoryManager() {} virtual ~RTDyldMemoryManager(); @@ -86,6 +89,27 @@ public: return getSymbolAddressInProcess(Name); } + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) { + return 0; + } + /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. /// @@ -109,7 +133,7 @@ public: /// address space can use this call to remap the section addresses for the /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *) {} + const object::ObjectFile &) {} /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 3605b9e..08cfa39 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,25 +15,25 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include namespace llvm { namespace object { class ObjectFile; + template class OwningBinary; } class RuntimeDyldImpl; class RuntimeDyldCheckerImpl; -class ObjectImage; class RuntimeDyld { friend class RuntimeDyldCheckerImpl; - RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; - void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; + RuntimeDyld(const RuntimeDyld &) = delete; + void operator=(const RuntimeDyld &) = delete; // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public // interface. @@ -46,32 +46,49 @@ protected: // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + + /// \brief Information about the loaded object. + class LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual ~LoadedObjectInfo() {} + + virtual object::OwningBinary + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t getSectionLoadAddress(StringRef Name) const; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + unsigned BeginIdx, EndIdx; + }; + RuntimeDyld(RTDyldMemoryManager *); ~RuntimeDyld(); - /// Prepare the object contained in the input buffer for execution. - /// Ownership of the input buffer is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input buffer will be deleted. - std::unique_ptr - loadObject(std::unique_ptr InputBuffer); - - /// Prepare the referenced object file for execution. - /// Ownership of the input object is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input object will be deleted. - std::unique_ptr - loadObject(std::unique_ptr InputObject); + /// Add the referenced object file to the list of objects to be loaded and + /// relocated. + std::unique_ptr loadObject(const object::ObjectFile &O); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). void *getSymbolAddress(StringRef Name) const; - /// Get the address of the target copy of the symbol. This is the address - /// used for relocation. + /// Get the address of the target copy of the symbol (works for both exported + /// and non-exported symbols). This is the address used for relocation. uint64_t getSymbolLoadAddress(StringRef Name) const; + /// Get the address of the target copy of the symbol (works for exported + /// symbols only). This is the address used for relocation. + uint64_t getExportedSymbolLoadAddress(StringRef Name) const; + /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 35ceba2..23936a6 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -52,6 +52,7 @@ class raw_ostream; /// /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' /// | 'next_pc' '(' symbol ')' +/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')' /// | symbol /// /// binary_expr = expr '+' expr diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 1368563..b825aff 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -35,8 +35,8 @@ namespace llvm { /// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. class SectionMemoryManager : public RTDyldMemoryManager { - SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; + SectionMemoryManager(const SectionMemoryManager&) = delete; + void operator=(const SectionMemoryManager&) = delete; public: SectionMemoryManager() { } diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 5ff48d6..443892b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -282,6 +282,11 @@ public: AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Since attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 7c7dd2c..185fc29 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -82,8 +82,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits; - BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; - void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; /// \brief Constructor. /// @@ -208,6 +208,14 @@ public: return const_cast(this)->getUniquePredecessor(); } + /// Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. This method is analogous to + /// getUniquePredeccessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast(this)->getUniqueSuccessor(); + } + //===--------------------------------------------------------------------===// /// Instruction iterator methods /// diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index c8be8bd..8476431 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -16,6 +16,7 @@ #define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -84,6 +85,8 @@ public: typedef PredIterator pred_iterator; typedef PredIterator const_pred_iterator; +typedef llvm::iterator_range pred_range; +typedef llvm::iterator_range pred_const_range; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -93,8 +96,15 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } - - +inline bool pred_empty(const BasicBlock *BB) { + return pred_begin(BB) == pred_end(BB); +} +inline pred_range predecessors(BasicBlock *BB) { + return pred_range(pred_begin(BB), pred_end(BB)); +} +inline pred_const_range predecessors(const BasicBlock *BB) { + return pred_const_range(pred_begin(BB), pred_end(BB)); +} //===----------------------------------------------------------------------===// // BasicBlock succ_iterator definition @@ -244,6 +254,8 @@ public: typedef SuccIterator succ_iterator; typedef SuccIterator succ_const_iterator; +typedef llvm::iterator_range succ_range; +typedef llvm::iterator_range succ_const_range; inline succ_iterator succ_begin(BasicBlock *BB) { return succ_iterator(BB->getTerminator()); @@ -257,6 +269,16 @@ inline succ_iterator succ_end(BasicBlock *BB) { inline succ_const_iterator succ_end(const BasicBlock *BB) { return succ_const_iterator(BB->getTerminator(), true); } +inline bool succ_empty(const BasicBlock *BB) { + return succ_begin(BB) == succ_end(BB); +} +inline succ_range successors(BasicBlock *BB) { + return succ_range(succ_begin(BB), succ_end(BB)); +} +inline succ_const_range successors(const BasicBlock *BB) { + return succ_const_range(succ_begin(BB), succ_end(BB)); +} + template struct isPodLike > { static const bool value = isPodLike::value; diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index df08257..a4ea243 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -78,7 +78,7 @@ public: InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } + explicit operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called. /// diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 3e77a77..4d4c15f 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -49,7 +49,7 @@ private: friend class Module; Comdat(); Comdat(SelectionKind SK, StringMapEntry *Name); - Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + Comdat(const Comdat &) = delete; // Points to the map in Module. StringMapEntry *Name; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index d26991e..75499e0 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &) LLVM_DELETED_FUNCTION; - Constant(const Constant &) LLVM_DELETED_FUNCTION; + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; void anchor() override; protected: diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 3d39289..5e8cd34 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -37,7 +37,7 @@ namespace llvm { -/// ConstantRange - This class represents an range of values. +/// This class represents a range of values. /// class ConstantRange { APInt Lower, Upper; @@ -59,7 +59,7 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// makeICmpRegion - Produce the smallest range that contains all values that + /// Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value /// contained within Other. /// @@ -69,47 +69,46 @@ public: static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); - /// getLower - Return the lower value for this range... + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } - /// getUpper - Return the upper value for this range... + /// Return the upper value for this range. /// const APInt &getUpper() const { return Upper; } - /// getBitWidth - get the bit width of this ConstantRange + /// Get the bit width of this ConstantRange. /// uint32_t getBitWidth() const { return Lower.getBitWidth(); } - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type + /// Return true if this set contains all of the elements possible + /// for this data-type. /// bool isFullSet() const; - /// isEmptySet - Return true if this set contains no members. + /// Return true if this set contains no members. /// bool isEmptySet() const; - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) + /// Return true if this set wraps around the top of the range. + /// For example: [100, 8). /// bool isWrappedSet() const; - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). + /// Return true if this set wraps around the INT_MIN of + /// its bitwidth. For example: i8 [120, 140). /// bool isSignWrappedSet() const; - /// contains - Return true if the specified value is in the set. + /// Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; - /// contains - Return true if the other range is a subset of this one. + /// Return true if the other range is a subset of this one. /// bool contains(const ConstantRange &CR) const; - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. + /// If this set contains a single element, return it, otherwise return null. /// const APInt *getSingleElement() const { if (Upper == Lower + 1) @@ -117,35 +116,31 @@ public: return nullptr; } - /// isSingleElement - Return true if this set contains exactly one member. + /// Return true if this set contains exactly one member. /// bool isSingleElement() const { return getSingleElement() != nullptr; } - /// getSetSize - Return the number of elements in this set. + /// Return the number of elements in this set. /// APInt getSetSize() const; - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. + /// Return the largest unsigned value contained in the ConstantRange. /// APInt getUnsignedMax() const; - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. + /// Return the smallest unsigned value contained in the ConstantRange. /// APInt getUnsignedMin() const; - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. + /// Return the largest signed value contained in the ConstantRange. /// APInt getSignedMax() const; - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. + /// Return the smallest signed value contained in the ConstantRange. /// APInt getSignedMin() const; - /// operator== - Return true if this range is equal to another range. + /// Return true if this range is equal to another range. /// bool operator==(const ConstantRange &CR) const { return Lower == CR.Lower && Upper == CR.Upper; @@ -154,15 +149,14 @@ public: return !operator==(CR); } - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; /// \brief Subtract the specified range from this range (aka relative /// complement of the sets). ConstantRange difference(const ConstantRange &CR) const; - /// intersectWith - Return the range that results from the intersection of + /// Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the /// smallest possible set size that does so. Because there may be two @@ -171,7 +165,7 @@ public: /// ConstantRange intersectWith(const ConstantRange &CR) const; - /// unionWith - Return the range that results from the union of this range + /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included @@ -179,85 +173,84 @@ public: /// ConstantRange unionWith(const ConstantRange &CR) const; - /// zeroExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// zero extended to BitWidth. ConstantRange zeroExtend(uint32_t BitWidth) const; - /// signExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// sign extended to BitWidth. ConstantRange signExtend(uint32_t BitWidth) const; - /// truncate - Return a new range in the specified integer type, which must be + /// Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// truncated to the specified type. ConstantRange truncate(uint32_t BitWidth) const; - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is zero extended, truncated, or left alone to make it that width. ConstantRange zextOrTrunc(uint32_t BitWidth) const; - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is sign extended, truncated, or left alone to make it that width. ConstantRange sextOrTrunc(uint32_t BitWidth) const; - /// add - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an addition of a value in this range and a value in \p Other. ConstantRange add(const ConstantRange &Other) const; - /// sub - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a subtraction of a value in this range and a value in \p Other. ConstantRange sub(const ConstantRange &Other) const; - /// multiply - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a multiplication of a value in this range and a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange multiply(const ConstantRange &Other) const; - /// smax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a signed maximum of a value in this range and a value in \p Other. ConstantRange smax(const ConstantRange &Other) const; - /// umax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned maximum of a value in this range and a value in \p Other. ConstantRange umax(const ConstantRange &Other) const; - /// udiv - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; - /// binaryAnd - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; - /// binaryOr - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-or of a value in this range by a value in \p Other. ConstantRange binaryOr(const ConstantRange &Other) const; - /// shl - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange shl(const ConstantRange &Other) const; - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. + /// Return a new range representing the possible values resulting from a + /// logical right shift of a value in this range and a value in \p Other. ConstantRange lshr(const ConstantRange &Other) const; - /// inverse - Return a new range that is the logical not of the current set. + /// Return a new range that is the logical not of the current set. /// ConstantRange inverse() const; - /// print - Print out the bounds to a stream... + /// Print out the bounds to a stream. /// void print(raw_ostream &OS) const; - /// dump - Allow printing from a debugger easily... + /// Allow printing from a debugger easily. /// void dump() const; }; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 1b0e1b7..59be653 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -46,8 +46,8 @@ template struct ConstantAggrKeyType; /// @brief Class for constant integers. class ConstantInt : public Constant { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -228,8 +228,8 @@ public: class ConstantFP : public Constant { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -294,8 +294,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantAggregateZero(const ConstantAggregateZero &) = delete; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -325,6 +325,9 @@ public: /// index. Constant *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -338,7 +341,7 @@ public: /// class ConstantArray : public Constant { friend struct ConstantAggrKeyType; - ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; + ConstantArray(const ConstantArray &) = delete; protected: ConstantArray(ArrayType *T, ArrayRef Val); public: @@ -380,7 +383,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantAggrKeyType; - ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; + ConstantStruct(const ConstantStruct &) = delete; protected: ConstantStruct(StructType *T, ArrayRef Val); public: @@ -439,7 +442,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantAggrKeyType; - ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; + ConstantVector(const ConstantVector &) = delete; protected: ConstantVector(VectorType *T, ArrayRef Val); public: @@ -488,8 +491,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantPointerNull(const ConstantPointerNull &) = delete; protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -539,8 +542,8 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataSequential(const ConstantDataSequential &) = delete; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} @@ -650,8 +653,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataArray(const ConstantDataArray &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -673,6 +676,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -702,8 +714,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataVector(const ConstantDataVector &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -725,6 +737,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -753,7 +774,7 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: @@ -1165,8 +1186,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + UndefValue(const UndefValue &) = delete; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: @@ -1196,6 +1217,9 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 3a50609..97a7b83 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" @@ -65,22 +66,34 @@ namespace llvm { Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value - SmallVector AllEnumTypes; - /// Use TrackingVH to collect RetainTypes, since they can be updated - /// later on. - SmallVector, 4> AllRetainTypes; - SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector, 4> AllImportedModules; + SmallVector AllEnumTypes; + /// Track the RetainTypes, since they can be updated later on. + SmallVector AllRetainTypes; + SmallVector AllSubprograms; + SmallVector AllGVs; + SmallVector AllImportedModules; + + /// \brief Track nodes that may be unresolved. + SmallVector UnresolvedNodes; + bool AllowUnresolvedNodes; /// Each subprogram's preserved local variables. - DenseMap>> PreservedVariables; + DenseMap> PreservedVariables; + + DIBuilder(const DIBuilder &) = delete; + void operator=(const DIBuilder &) = delete; - DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; + /// \brief Create a temporary. + /// + /// Create an \a temporary node and track it in \a UnresolvedNodes. + void trackIfUnresolved(MDNode *N); public: - explicit DIBuilder(Module &M); + /// \brief Construct a builder for a module. + /// + /// If \c AllowUnresolved, collect unresolved nodes attached to the module + /// in order to resolve cycles during \a finalize(). + explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. @@ -159,8 +172,12 @@ namespace llvm { /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. @@ -316,13 +333,8 @@ namespace llvm { /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -330,40 +342,30 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @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, - Constant *Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + Constant *Val); /// \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 = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + StringRef Val); /// \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 = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, + StringRef Name, + DIType Ty, + DIArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. @@ -423,10 +425,11 @@ namespace llvm { StringRef UniqueIdentifier = StringRef()); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableForwardDecl( + DICompositeType createReplaceableCompositeType( unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + uint64_t AlignInBits = 0, unsigned Flags = DIDescriptor::FlagFwdDecl, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -437,10 +440,10 @@ namespace llvm { DIBasicType createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef Elements); + DIArray getOrCreateArray(ArrayRef Elements); /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef Elements); + DITypeArray getOrCreateTypeArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. @@ -497,15 +500,16 @@ namespace llvm { /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr); - /// createPieceExpression - Create a descriptor to describe one part + /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBytes Offset of the piece in bytes. - /// @param SizeInBytes Size of the piece in bytes. - DIExpression createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes); + /// @param OffsetInBits Offset of the piece in bits. + /// @param SizeInBits Size of the piece in bits. + DIExpression createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -685,6 +689,20 @@ namespace llvm { Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 4580a4f..9479ba4 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -53,6 +53,11 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a' }; +// FIXME: Currently the DataLayout string carries a "preferred alignment" +// for types. As the DataLayout is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + /// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, @@ -228,6 +233,8 @@ public: return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + unsigned getStackAlignment() const { return StackNaturalAlign; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WINCOFF; } diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 22a2138..d2e5975 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,11 +18,11 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -66,10 +66,10 @@ class DIHeaderFieldIterator public: DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) + explicit DIHeaderFieldIterator(StringRef Header) : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } + const StringRef *operator->() const { return &Current; } DIHeaderFieldIterator &operator++() { increment(); return *this; @@ -99,6 +99,16 @@ public: return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); } + /// \brief Get the current field as a number. + /// + /// Convert the current field into a number. Return \c 0 on error. + template T getNumber() const { + T Int; + if (getCurrent().getAsInteger(0, Int)) + return 0; + return Int; + } + private: void increment() { assert(Current.data() != nullptr && "Cannot increment past the end"); @@ -122,27 +132,21 @@ public: /// The three accessibility flags are mutually exclusive and rolled together /// in the first two bits. enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - 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, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic }; + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl &SplitFlags); + protected: const MDNode *DbgNode; @@ -168,42 +172,47 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator->() const { return const_cast(DbgNode); } + MDNode *get() const { return const_cast(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // 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 != nullptr; } + explicit operator bool() const { return DbgNode != nullptr; } bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - StringRef getHeader() const { - return getStringField(0); - } + StringRef getHeader() const { return getStringField(0); } size_t getNumHeaderFields() const { return std::distance(DIHeaderFieldIterator(getHeader()), DIHeaderFieldIterator()); } - StringRef getHeaderField(unsigned Index) const { + DIHeaderFieldIterator header_begin() const { + return DIHeaderFieldIterator(getHeader()); + } + DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); } + + DIHeaderFieldIterator getHeaderIterator(unsigned Index) const { // Since callers expect an empty string for out-of-range accesses, we can't // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) if (!Index) - return *I; - return StringRef(); + return I; + return header_end(); + } + + StringRef getHeaderField(unsigned Index) const { + return *getHeaderIterator(Index); } template T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; + return getHeaderIterator(Index).getNumber(); } uint16_t getTag() const { return getHeaderFieldAs(0); } @@ -238,6 +247,19 @@ public: void replaceAllUsesWith(MDNode *D); }; +#define RETURN_FROM_RAW(VALID, DEFAULT) \ + do { \ + if (auto *N = getRaw()) \ + return VALID; \ + return DEFAULT; \ + } while (false) +#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ + do { \ + if (auto *N = getRaw()) \ + return DESC(dyn_cast_or_null(VALID)); \ + return DESC(static_cast(nullptr)); \ + } while (false) + /// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; @@ -258,9 +280,7 @@ public: unsigned getNumElements() const { return DbgNode ? DbgNode->getNumOperands() : 0; } - T getElement(unsigned Idx) const { - return getFieldAs(Idx); - } + T getElement(unsigned Idx) const { return getFieldAs(Idx); } }; typedef DITypedArray DIArray; @@ -282,6 +302,7 @@ public: }; template class DIRef; +typedef DIRef DIDescriptorRef; typedef DIRef DIScopeRef; typedef DIRef DITypeRef; typedef DITypedArray DITypeArray; @@ -371,6 +392,12 @@ template StringRef DIRef::getName() const { return MS->getString(); } +/// \brief Handle fields that are references to DIDescriptors. +template <> +DIDescriptorRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// \brief Specialize DIRef constructor for DIDescriptorRef. +template <> DIRef::DIRef(const Metadata *V); + /// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DIScopeRef. @@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DITypeRef. template <> DIRef::DIRef(const Metadata *V); -/// \briefThis is a wrapper for a type. +/// \brief 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. @@ -392,7 +419,7 @@ protected: public: explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { + operator DITypeRef() const { assert(isType() && "constructing DITypeRef from an MDNode that is not a type"); return DITypeRef(&*getRef()); @@ -402,20 +429,12 @@ public: DIScopeRef getContext() const { return getFieldAs(2); } StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs(4); - } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } + uint64_t getSizeInBits() const { return getHeaderFieldAs(3); } + uint64_t getAlignInBits() const { return getHeaderFieldAs(4); } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs(5); - } + uint64_t getOffsetInBits() const { return getHeaderFieldAs(5); } unsigned getFlags() const { return getHeaderFieldAs(6); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; @@ -499,6 +518,7 @@ public: // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -512,20 +532,26 @@ public: assert(!isSubroutineType() && "no elements for DISubroutineType"); return getFieldAs(4); } + +private: template void setArrays(DITypedArray Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); + assert( + (!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); setArraysHelper(Elements, TParams); } - unsigned getRunTimeLang() const { - return getHeaderFieldAs(7); - } + +public: + unsigned getRunTimeLang() const { return getHeaderFieldAs(7); } DITypeRef getContainingType() const { return getFieldAs(5); } +private: /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); + +public: DIArray getTemplateParams() const { return getFieldAs(6); } MDString *getIdentifier() const; @@ -663,7 +689,6 @@ public: unsigned isRValueReference() const { return (getFlags() & FlagRValueReference) != 0; } - }; /// \brief This is a wrapper for a lexical block. @@ -671,12 +696,8 @@ class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs(2); - } + unsigned getLineNumber() const { return getHeaderFieldAs(1); } + unsigned getColumnNumber() const { return getHeaderFieldAs(2); } bool Verify() const; }; @@ -685,6 +706,8 @@ class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { + // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but + // then we check if it's a subprogram? WHAT?!? if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); @@ -713,18 +736,11 @@ public: class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - StringRef getFilename() const { return getFieldAs(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(3).getDirectory(); - } bool Verify() const; }; @@ -732,19 +748,12 @@ public: class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); - } + Metadata *getValue() const; bool Verify() const; }; @@ -763,7 +772,7 @@ public: unsigned isLocalToUnit() const { return getHeaderFieldAs(5); } unsigned isDefinition() const { return getHeaderFieldAs(6); } - DIScopeRef getContext() const { return getFieldAs(1); } + DIScope getContext() const { return getFieldAs(1); } StringRef getFilename() const { return getFieldAs(2).getFilename(); } StringRef getDirectory() const { return getFieldAs(2).getDirectory(); @@ -807,11 +816,6 @@ public: return (getHeaderFieldAs(3) & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs(3) & FlagIndirectVariable) != 0; - } - /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -831,7 +835,13 @@ public: void printExtendedName(raw_ostream &OS) const; }; -/// \brief A complex location expression. +/// \brief A complex location expression in postfix notation. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. class DIExpression : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -854,24 +864,91 @@ public: uint64_t getElement(unsigned Idx) const; /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; + bool isBitPiece() const; + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + class iterator; + /// \brief A lightweight wrapper around an element of a DIExpression. + class Operand { + friend class iterator; + DIHeaderFieldIterator I; + Operand() {} + Operand(DIHeaderFieldIterator I) : I(I) {} + public: + /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments. + /// Argument 0 is the operand itself. + uint64_t getArg(unsigned N) const { + DIHeaderFieldIterator In = I; + std::advance(In, N); + return In.getNumber(); + } + operator uint64_t () const { return I.getNumber(); } + /// \brief Returns underlying DIHeaderFieldIterator. + const DIHeaderFieldIterator &getBase() const { return I; } + /// \brief Returns the next operand. + Operand getNext() const; + }; + + /// \brief An iterator for DIExpression elements. + class iterator : public std::iterator { + friend class Operand; + DIHeaderFieldIterator I; + Operand Tmp; + iterator(DIHeaderFieldIterator I) : I(I) {} + public: + iterator() {} + iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {} + const Operand &operator*() { return Tmp = Operand(I); } + const Operand *operator->() { return &(Tmp = Operand(I)); } + iterator &operator++() { + increment(); + return *this; + } + iterator operator++(int) { + iterator X(*this); + increment(); + return X; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return !(*this == X); } + + private: + void increment() { + switch (**this) { + case dwarf::DW_OP_bit_piece: std::advance(I, 3); break; + case dwarf::DW_OP_plus: std::advance(I, 2); break; + case dwarf::DW_OP_deref: std::advance(I, 1); break; + default: + llvm_unreachable("unsupported operand"); + } + } + }; + + iterator begin() const; + iterator end() const; }; /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { + MDLocation *getRaw() const { return dyn_cast_or_null(get()); } + 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); } + unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } + unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); } + DIScope getScope() const { + RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); + } + DILocation getOrigLocation() const { + RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt()); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -892,7 +969,9 @@ public: // sure this location is a lexical block before retrieving its // value. return getScope().isLexicalBlockFile() - ? getFieldAs(2).getDiscriminator() + ? DILexicalBlockFile( + cast(cast(DbgNode)->getScope())) + .getDiscriminator() : 0; } @@ -951,14 +1030,18 @@ class DIImportedEntity : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: + DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs(1); } - DIScopeRef getEntity() const { return getFieldAs(2); } + DIDescriptorRef getEntity() const { return getFieldAs(2); } unsigned getLineNumber() const { return getHeaderFieldAs(1); } StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; +#undef RETURN_FROM_RAW +#undef RETURN_DESCRIPTOR_FROM_RAW + /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1015,6 +1098,9 @@ public: /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); + /// \brief Process DIExpression. + void processExpression(DIExpression Expr); + /// \brief Clear all lists. void reset(); @@ -1033,7 +1119,8 @@ private: public: typedef SmallVectorImpl::const_iterator compile_unit_iterator; typedef SmallVectorImpl::const_iterator subprogram_iterator; - typedef SmallVectorImpl::const_iterator global_variable_iterator; + typedef SmallVectorImpl::const_iterator + global_variable_iterator; typedef SmallVectorImpl::const_iterator type_iterator; typedef SmallVectorImpl::const_iterator scope_iterator; diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def new file mode 100644 index 0000000..d5de868 --- /dev/null +++ b/include/llvm/IR/DebugInfoFlags.def @@ -0,0 +1,36 @@ +//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through debug info flags. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#ifndef HANDLE_DI_FLAG +#error "Missing macro definition of HANDLE_DI_FLAG" +#endif + +HANDLE_DI_FLAG(1, Private) +HANDLE_DI_FLAG(2, Protected) +HANDLE_DI_FLAG(3, Public) +HANDLE_DI_FLAG((1 << 2), FwdDecl) +HANDLE_DI_FLAG((1 << 3), AppleBlock) +HANDLE_DI_FLAG((1 << 4), BlockByrefStruct) +HANDLE_DI_FLAG((1 << 5), Virtual) +HANDLE_DI_FLAG((1 << 6), Artificial) +HANDLE_DI_FLAG((1 << 7), Explicit) +HANDLE_DI_FLAG((1 << 8), Prototyped) +HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) +HANDLE_DI_FLAG((1 << 10), ObjectPointer) +HANDLE_DI_FLAG((1 << 11), Vector) +HANDLE_DI_FLAG((1 << 12), StaticMember) +HANDLE_DI_FLAG((1 << 13), LValueReference) +HANDLE_DI_FLAG((1 << 14), RValueReference) + +#undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h new file mode 100644 index 0000000..4534a14 --- /dev/null +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -0,0 +1,1669 @@ +//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations for metadata specific to debug info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGINFOMETADATA_H +#define LLVM_IR_DEBUGINFOMETADATA_H + +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } + +namespace llvm { + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef MDs); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempMDLocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } +}; + +/// \brief Tagged DWARF-like metadata node. +/// +/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, +/// defined in llvm/Support/Dwarf.h). Called \a DebugNode because it's +/// potentially used for non-DWARF output. +class DebugNode : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + +protected: + DebugNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops1, ArrayRef Ops2 = None) + : MDNode(C, ID, Storage, Ops1, Ops2) { + assert(Tag < 1u << 16); + SubclassData16 = Tag; + } + ~DebugNode() {} + + template Ty *getOperandAs(unsigned I) const { + return cast_or_null(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + +public: + unsigned getTag() const { return SubclassData16; } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case GenericDebugNodeKind: + case MDSubrangeKind: + case MDEnumeratorKind: + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + case MDTemplateTypeParameterKind: + case MDTemplateValueParameterKind: + case MDGlobalVariableKind: + case MDLocalVariableKind: + case MDExpressionKind: + case MDObjCPropertyKind: + case MDImportedEntityKind: + return true; + } + } +}; + +/// \brief Generic tagged DWARF-like metadata node. +/// +/// An un-specialized DWARF-like metadata node. The first operand is a +/// (possibly empty) null-separated \a MDString header that contains arbitrary +/// fields. The remaining operands are \a dwarf_operands(), and are pointers +/// to other metadata. +class GenericDebugNode : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + GenericDebugNode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef Ops1, + ArrayRef Ops2) + : DebugNode(C, GenericDebugNodeKind, Storage, Tag, Ops1, Ops2) { + setHash(Hash); + } + ~GenericDebugNode() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true); + + TempGenericDebugNode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector(dwarf_op_begin(), dwarf_op_end())); + } + +public: + unsigned getHash() const { return SubclassData32; } + + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + + /// \brief Return a (temporary) clone of this. + TempGenericDebugNode clone() const { return cloneImpl(); } + + unsigned getTag() const { return SubclassData16; } + StringRef getHeader() const { return getStringOperand(0); } + + op_iterator dwarf_op_begin() const { return op_begin() + 1; } + op_iterator dwarf_op_end() const { return op_end(); } + op_range dwarf_operands() const { + return op_range(dwarf_op_begin(), dwarf_op_end()); + } + + unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } + const MDOperand &getDwarfOperand(unsigned I) const { + return getOperand(I + 1); + } + void replaceDwarfOperandWith(unsigned I, Metadata *New) { + replaceOperandWith(I + 1, New); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == GenericDebugNodeKind; + } +}; + +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class MDSubrange : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t Lo; + + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, + None), + Count(Count), Lo(Lo) {} + ~MDSubrange() {} + + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLo()); + } + +public: + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + + TempMDSubrange clone() const { return cloneImpl(); } + + int64_t getLo() const { return Lo; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class MDEnumerator : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef Ops) + : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~MDEnumerator() {} + + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempMDEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempMDEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class MDScope : public DebugNode { +protected: + MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops) {} + ~MDScope() {} + +public: + Metadata *getFile() const { return getOperand(0); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + return true; + } + } +}; + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class MDType : public MDScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~MDType() {} + +public: + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class MDBasicType : public MDType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef Ops) + : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~MDBasicType() {} + + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempMDBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempMDBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDBasicTypeKind; + } +}; + +/// \brief Base class for MDDerivedType and MDCompositeType. +/// +/// TODO: Delete; they're not really related. +class MDDerivedTypeBase : public MDType { +protected: + MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDDerivedTypeBase() {} + +public: + Metadata *getBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind || + MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class MDDerivedType : public MDDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~MDDerivedType() {} + + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempMDDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempMDDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// TODO: Separate out types that need this extra operand: pointer-to-member + /// types and member fields (static members and ivars). + Metadata *getExtraData() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind; + } +}; + +/// \brief Base class for MDCompositeType and MDSubroutineType. +/// +/// TODO: Delete; they're not really related. +class MDCompositeTypeBase : public MDDerivedTypeBase { + unsigned RuntimeLang; + +protected: + MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~MDCompositeTypeBase() {} + +public: + Metadata *getElements() const { return getOperand(4); } + Metadata *getVTableHolder() const { return getOperand(5); } + Metadata *getTemplateParams() const { return getOperand(6); } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + MDString *getRawIdentifier() const { return getOperandAs(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(MDTuple *Elements) { +#ifndef NDEBUG + if (auto *Old = cast_or_null(getElements())) + for (const auto &Op : Old->operands()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements); + } + void replaceVTableHolder(Metadata *VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(MDTuple *TemplateParams) { + replaceOperandWith(6, TemplateParams); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class MDCompositeType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDCompositeType() {} + + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, + getCanonicalMDString(Context, Identifier), Storage, + ShouldCreate); + } + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempMDCompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempMDCompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind; + } +}; + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class MDSubroutineType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~MDSubroutineType() {} + + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempMDSubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempMDSubroutineType clone() const { return cloneImpl(); } + + Metadata *getTypeArray() const { return getElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class MDFile : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) + : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~MDFile() {} + + static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempMDFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempMDFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs(0); } + MDString *getRawDirectory() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDFileKind; + } +}; + +/// \brief Compile unit. +class MDCompileUnit : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + + MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, ArrayRef Ops) + : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} + ~MDCompileUnit() {} + + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, Storage, ShouldCreate); + } + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true); + + TempMDCompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities()); + } + +public: + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + + TempMDCompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + StringRef getProducer() const { return getStringOperand(1); } + StringRef getFlags() const { return getStringOperand(2); } + StringRef getSplitDebugFilename() const { return getStringOperand(3); } + Metadata *getEnumTypes() const { return getOperand(4); } + Metadata *getRetainedTypes() const { return getOperand(5); } + Metadata *getSubprograms() const { return getOperand(6); } + Metadata *getGlobalVariables() const { return getOperand(7); } + Metadata *getImportedEntities() const { return getOperand(8); } + + MDString *getRawProducer() const { return getOperandAs(1); } + MDString *getRawFlags() const { return getOperandAs(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs(3); + } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// deleted on a uniquing collision. In practice, uniquing collisions on \a + /// MDCompileUnit should be fairly rare. + /// @{ + void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); } + void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompileUnitKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class MDSubprogram : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef Ops) + : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~MDSubprogram() {} + + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables, Storage, + ShouldCreate); + } + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunction(), getTemplateParams(), + getDeclaration(), getVariables()); + } + +public: + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + + TempMDSubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + Metadata *getScope() const { return getOperand(1); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawLinkageName() const { return getOperandAs(4); } + + Metadata *getType() const { return getOperand(5); } + Metadata *getContainingType() const { return getOperand(6); } + + Metadata *getFunction() const { return getOperand(7); } + Metadata *getTemplateParams() const { return getOperand(8); } + Metadata *getDeclaration() const { return getOperand(9); } + Metadata *getVariables() const { return getOperand(10); } + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubprogramKind; + } +}; + +class MDLexicalBlockBase : public MDScope { +protected: + MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef Ops) + : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~MDLexicalBlockBase() {} + +public: + Metadata *getScope() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind || + MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDLexicalBlock : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~MDLexicalBlock() {} + + static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempMDLexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempMDLexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind; + } +}; + +class MDLexicalBlockFile : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + MDLexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~MDLexicalBlockFile() {} + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempMDLexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempMDLexicalBlockFile clone() const { return cloneImpl(); } + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDNamespace : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef Ops) + : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~MDNamespace() {} + + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempMDNamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + StringRef Name, unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempMDNamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class MDTemplateParameter : public DebugNode { +protected: + MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : DebugNode(Context, ID, Storage, Tag, Ops) {} + ~MDTemplateParameter() {} + +public: + StringRef getName() const { return getStringOperand(0); } + Metadata *getType() const { return getOperand(1); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind || + MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +class MDTemplateTypeParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~MDTemplateTypeParameter() {} + + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + (Name, Type)) + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempMDTemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind; + } +}; + +class MDTemplateValueParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, + Ops) {} + ~MDTemplateValueParameter() {} + + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempMDTemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class MDVariable : public DebugNode { + unsigned Line; + +protected: + MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~MDVariable() {} + +public: + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + StringRef getName() const { return getStringOperand(1); } + Metadata *getFile() const { return getOperand(2); } + Metadata *getType() const { return getOperand(3); } + + MDString *getRawName() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind || + MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class MDGlobalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef Ops) + : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~MDGlobalVariable() {} + + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempMDGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +public: + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, StringRef Name, StringRef LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempMDGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + StringRef getDisplayName() const { return getStringOperand(4); } + StringRef getLinkageName() const { return getStringOperand(5); } + Metadata *getVariable() const { return getOperand(6); } + Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + + MDString *getRawLinkageName() const { return getOperandAs(5); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class MDLocalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef Ops) + : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~MDLocalVariable() {} + + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, InlinedAt, Storage, + ShouldCreate); + } + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags(), + getInlinedAt()); + } + +public: + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + + TempMDLocalVariable clone() const { return cloneImpl(); } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + Metadata *getInlinedAt() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Drop fake DW_TAG_expression and separate from DebugNode. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class MDExpression : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector Elements; + + MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + Elements(Elements.begin(), Elements.end()) {} + ~MDExpression() {} + + static MDExpression *getImpl(LLVMContext &Context, + ArrayRef Elements, StorageType Storage, + bool ShouldCreate = true); + + TempMDExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + + TempMDExpression clone() const { return cloneImpl(); } + + ArrayRef getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + typedef ArrayRef::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a MDExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDExpressionKind; + } +}; + +class MDObjCProperty : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef Ops) + : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~MDObjCProperty() {} + + static MDObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempMDObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(MDObjCProperty, + (StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(MDObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempMDObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + Metadata *getFile() const { return getOperand(1); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + Metadata *getType() const { return getOperand(4); } + + MDString *getRawName() const { return getOperandAs(0); } + MDString *getRawGetterName() const { return getOperandAs(2); } + MDString *getRawSetterName() const { return getOperandAs(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDObjCPropertyKind; + } +}; + +class MDImportedEntity : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~MDImportedEntity() {} + + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempMDImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempMDImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getEntity() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDImportedEntityKind; + } +}; + +} // end namespace llvm + +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + +#endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 3d969a8..86e6441 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -15,51 +15,41 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { - template struct DenseMapInfo; - class MDNode; + class LLVMContext; class raw_ostream; + class MDNode; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { - friend struct DenseMapInfo; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } + TrackingMDNodeRef Loc; - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; } - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = nullptr); + static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, + MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -68,56 +58,54 @@ namespace llvm { static DebugLoc getFromDILexicalBlock(MDNode *N); /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } + bool isUnknown() const { return !Loc; } - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } + unsigned getLine() const; + unsigned getCol() const; /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; + MDNode *getScope() const; + MDNode *getScope(const LLVMContext &) const { return getScope(); } /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; + MDNode *getInlinedAt() const; + MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; + const LLVMContext &) const { + return getScopeAndInlinedAt(Scope, IA); + } /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode(const LLVMContext &Ctx) const; + MDNode *getScopeNode() const; + MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; + DebugLoc getFnDebugLoc() const; + DebugLoc getFnDebugLoc(const LLVMContext &) const { + return getFnDebugLoc(); + } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; + MDNode *getAsMDNode() const; + MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - void dump(const LLVMContext &Ctx) const; + void dump() const; + void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(const LLVMContext &Ctx, raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; - template <> - struct DenseMapInfo { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; } // end namespace llvm #endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 534d1e5..76f8064 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; - const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; FunctionType(Type *Result, ArrayRef Params, bool IsVarArgs); public: @@ -123,6 +123,9 @@ public: typedef Type::subtype_iterator param_iterator; param_iterator param_begin() const { return ContainedTys + 1; } param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef params() const { + return makeArrayRef(param_begin(), param_end()); + } /// Parameter type accessors. Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } @@ -185,8 +188,8 @@ public: /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &) LLVM_DELETED_FUNCTION; - const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { @@ -274,6 +277,9 @@ public: typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef const elements() const { + return makeArrayRef(element_begin(), element_end()); + } /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. @@ -302,8 +308,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; - const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; protected: SequentialType(TypeID TID, Type *ElType) @@ -329,8 +335,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; - const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -355,8 +361,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &) LLVM_DELETED_FUNCTION; - const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -440,8 +446,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &) LLVM_DELETED_FUNCTION; - const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index b592f89..c6a8854 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -45,6 +45,7 @@ enum DiagnosticSeverity { /// \brief Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Bitcode, DK_InlineAsm, DK_StackSize, DK_Linker, @@ -97,6 +98,8 @@ public: virtual void print(DiagnosticPrinter &DP) const = 0; }; +typedef std::function DiagnosticHandlerFunction; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e2d1ccc..c1f208e 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -31,6 +31,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); @@ -69,6 +74,13 @@ public: DominatorTree() : DominatorTreeBase(false) {} + DominatorTree(DominatorTree &&Arg) + : Base(std::move(static_cast(Arg))) {} + DominatorTree &operator=(DominatorTree &&RHS) { + Base::operator=(std::move(static_cast(RHS))); + return *this; + } + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { @@ -155,6 +167,43 @@ template <> struct GraphTraits }; /// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeAnalysis { +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DominatorTree Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Run the analysis pass over a function and produce a dominator tree. + DominatorTree run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "DominatorTreeAnalysis"; } + +private: + static char PassID; +}; + +/// \brief Printer pass for the \c DominatorTree. +class DominatorTreePrinterPass { + raw_ostream &OS; + +public: + explicit DominatorTreePrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreePrinterPass"; } +}; + +/// \brief Verifier pass for the \c DominatorTree. +struct DominatorTreeVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreeVerifierPass"; } +}; + +/// \brief Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 26d893b..0cd5afb 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ private: ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits; @@ -102,7 +105,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -110,8 +113,8 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; + Function(const Function&) = delete; + void operator=(const Function&) = delete; /// Do the actual lookup of an intrinsic ID when the query could not be /// answered from the cache. @@ -162,11 +165,11 @@ 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() >> 2); + return static_cast(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -215,6 +218,11 @@ public: return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -231,6 +239,9 @@ public: /// @brief removes the attributes from the list of attributes. void removeAttributes(unsigned i, AttributeSet attr); + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -448,12 +459,19 @@ public: bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// 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/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index a7d68ec..6f57dc2 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -19,11 +19,13 @@ #define LLVM_IR_GVMATERIALIZER_H #include +#include namespace llvm { class Function; class GlobalValue; class Module; +class StructType; class GVMaterializer { protected: @@ -50,6 +52,8 @@ public: /// Make sure the entire Module has been completely read. /// virtual std::error_code MaterializeModule(Module *M) = 0; + + virtual std::vector getIdentifiedStructTypes() const = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 075b570..d0672c8 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -28,8 +28,8 @@ template class GlobalAlias : public GlobalValue, public ilist_node { friend class SymbolTableListTraits; - void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; - GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + void operator=(const GlobalAlias &) = delete; + GlobalAlias(const GlobalAlias &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 546fea2..50deb08 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -24,7 +24,7 @@ class Comdat; class Module; class GlobalObject : public GlobalValue { - GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + GlobalObject(const GlobalObject &) = delete; protected: GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index e7b5d58..aaecc1d 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,7 +20,6 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" - #include namespace llvm { @@ -30,7 +29,7 @@ class PointerType; class Module; class GlobalValue : public Constant { - GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; + GlobalValue(const GlobalValue &) = delete; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4189ccb..d7b81a2 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -34,9 +34,9 @@ template class GlobalVariable : public GlobalObject, public ilist_node { friend class SymbolTableListTraits; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; - GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void operator=(const GlobalVariable &) = delete; + GlobalVariable(const GlobalVariable &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 088c7b4..33649d7 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -115,12 +115,10 @@ public: } /// \brief Set location information used by debugging information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } /// \brief Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// \brief If this builder has a current debug location, set it on the /// specified instruction. @@ -200,8 +198,8 @@ public: BasicBlock::iterator Point; DebugLoc DbgLoc; - InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; - InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; public: InsertPointGuard(IRBuilderBase &B) @@ -221,9 +219,9 @@ public: FastMathFlags FMF; MDNode *FPMathTag; - FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard(const FastMathFlagGuard &) = delete; FastMathFlagGuard &operator=( - const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + const FastMathFlagGuard &) = delete; public: FastMathFlagGuard(IRBuilderBase &B) @@ -429,11 +427,54 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + /// \brief Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. CallInst *CreateAssumption(Value *Cond); + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get + // the Value *. + CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); + private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -1246,11 +1287,23 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index afea0c3..7f2027b 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -58,7 +58,7 @@ public: PrintModulePass(); PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "PrintModulePass"; } }; @@ -75,7 +75,7 @@ public: PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Function &F); static StringRef name() { return "PrintFunctionPass"; } }; diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0..84ae9df 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -40,8 +40,8 @@ private: friend struct InlineAsmKeyType; friend class ConstantUniqueMap; - InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; - void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + InlineAsm(const InlineAsm &) = delete; + void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; bool HasSideEffects; diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd..0bb2854 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -127,20 +127,32 @@ typedef InstIterator, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range inst_range(Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range inst_range(const Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range inst_range(Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range inst_range(const Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 186fc88..e086282 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -83,7 +83,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, @@ -489,6 +489,19 @@ public: Instruction *InsertBefore = 0 ///< Place to insert the instruction ); + /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// + /// If the value is a pointer type and the destination an integer type, + /// creates a PtrToInt cast. If the value is an integer type and the + /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates + /// a bitcast. + static CastInst *CreateBitOrPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) @@ -551,6 +564,17 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// types is valid and a no-op. + /// + /// This ensures that any pointer<->integer cast has enough bits in the + /// integer and any other cast is a bitcast. + static bool isBitOrNoopPointerCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout *Layout = 0 ///< Optional DataLayout. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type @@ -650,8 +674,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - CmpInst() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + CmpInst() = delete; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index ba7791c..dfece3e 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -31,8 +31,8 @@ template class SymbolTableListTraits; class Instruction : public User, public ilist_node { - void operator=(const Instruction &) LLVM_DELETED_FUNCTION; - Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. @@ -201,7 +201,7 @@ public: void setAAMetadata(const AAMDNodes &N); /// setDebugLoc - Set the debug location information for this instruction. - void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index dcf19e0..83f9d04 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,8 +17,8 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" @@ -285,7 +285,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: StoreInst *clone_impl() const override; @@ -411,7 +411,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: FenceInst *clone_impl() const override; @@ -478,7 +478,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); @@ -634,7 +634,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: AtomicRMWInst *clone_impl() const override; public: @@ -845,6 +845,13 @@ public: return cast(Instruction::getType()); } + Type *getSourceElementType() const { + SequentialType *Ty = cast(getPointerOperandType()); + if (VectorType *VTy = dyn_cast(Ty)) + Ty = cast(VTy->getElementType()); + return Ty->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -1375,6 +1382,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -1958,7 +1968,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector Indices; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef Idxs, const Twine &NameStr); @@ -2088,7 +2098,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2163,6 +2173,8 @@ public: return block_begin() + getNumOperands(); } + op_range incoming_values() { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2295,7 +2307,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2562,7 +2574,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2871,7 +2883,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -3056,6 +3068,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief removes the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -3296,7 +3311,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnreachableInst *clone_impl() const override; diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index e3d7999..d434432 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -28,15 +28,16 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Metadata.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst() LLVM_DELETED_FUNCTION; - IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; - void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + IntrinsicInst() = delete; + IntrinsicInst(const IntrinsicInst&) = delete; + void operator=(const IntrinsicInst&) = delete; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// @@ -81,8 +82,14 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { return cast(getArgOperand(1)); } - MDNode *getExpression() const { return cast(getArgOperand(2)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(1))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -103,8 +110,14 @@ namespace llvm { return cast( const_cast(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { return cast(getArgOperand(2)); } - MDNode *getExpression() const { return cast(getArgOperand(3)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(3))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -322,6 +335,33 @@ namespace llvm { Value *getSrc() const { return const_cast(getArgOperand(1)); } }; + /// This represents the llvm.instrprof_increment intrinsic. + class InstrProfIncrementInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_increment; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + GlobalVariable *getName() const { + return cast( + const_cast(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast(const_cast(getArgOperand(1))); + } + + ConstantInt *getNumCounters() const { + return cast(const_cast(getArgOperand(2))); + } + + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(3))); + } + }; } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index acc0e9e..a66bd2c 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -41,7 +41,7 @@ namespace Intrinsic { #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; - + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef Tys = None); @@ -69,16 +69,17 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendArgument, TruncArgument, HalfVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument, + SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt } Kind; - + union { unsigned Integer_Width; unsigned Float_Width; @@ -87,8 +88,9 @@ namespace Intrinsic { unsigned Struct_NumElements; unsigned Argument_Info; }; - + enum ArgKind { + AK_Any, AK_AnyInteger, AK_AnyFloat, AK_AnyVector, @@ -96,25 +98,29 @@ namespace Intrinsic { }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return Argument_Info >> 2; + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return (ArgKind)(Argument_Info&3); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return (ArgKind)(Argument_Info & 7); } - + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } }; - + /// Return the IIT table descriptor for the specified intrinsic into an array /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); - + } // End Intrinsic namespace } // End llvm namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 98d48de..e89e65d 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -112,12 +112,19 @@ class LLVMMatchType // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType : LLVMMatchType; class LLVMTruncatedType : LLVMMatchType; +class LLVMVectorSameWidth + : LLVMMatchType { + ValueType ElTy = elty.VT; +} +class LLVMPointerTo : LLVMMatchType; +class LLVMVectorOfPointersToElt : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many class LLVMHalfElementsVectorType : LLVMMatchType; def llvm_void_ty : LLVMType; +def llvm_any_ty : LLVMType; def llvm_anyint_ty : LLVMType; def llvm_anyfloat_ty : LLVMType; def llvm_anyvector_ty : LLVMType; @@ -254,6 +261,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_framerecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -287,6 +298,12 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], [IntrReadWriteArgMem]>; +// A counter increment for instrumentation based profiling. +def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // @@ -394,6 +411,11 @@ 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]>; +// eh.begincatch takes a pointer returned by a landingpad instruction and +// returns the exception object pointer for the exception to be handled. +def int_eh_begincatch : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; +def int_eh_endcatch : Intrinsic<[], []>; + // __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. @@ -493,6 +515,24 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], llvm_vararg_ty], [Throws]>; + +//===------------------------ Garbage Collection Intrinsics ---------------===// +// These are documented in docs/Statepoint.rst + +def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty]>; + +def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +// Deprecated: will be removed in a couple of weeks +def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], + [llvm_i32_ty]>; +def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -539,6 +579,34 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +//===-------------------------- Masked Intrinsics -------------------------===// +// +def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, + llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMPointerTo<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +// Intrinsics to support bit sets. +def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// @@ -552,3 +620,4 @@ include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsBPF.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td new file mode 100644 index 0000000..6b5110b --- /dev/null +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -0,0 +1,22 @@ +//===- IntrinsicsBPF.td - Defines BPF 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 BPF-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +// Specialized loads from packet +let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." + def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; +} diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a88729..b566956 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic // class Hexagon_qi_qiqiqi_Intrinsic : Hexagon_Intrinsic; // // DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> @@ -434,7 +434,7 @@ class Hexagon_mem_memmemsisi_Intrinsic class Hexagon_sf_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_df_Intrinsic // @@ -490,21 +490,21 @@ class Hexagon_si_df_Intrinsic class Hexagon_sf_sfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsf_Intrinsic +// Hexagon_si_sfsf_Intrinsic // -class Hexagon_qi_sfsf_Intrinsic +class Hexagon_si_sfsf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsi_Intrinsic +// Hexagon_si_sfsi_Intrinsic // -class Hexagon_qi_sfsi_Intrinsic +class Hexagon_si_sfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // Hexagon_qi_sfqi_Intrinsic // @@ -519,7 +519,7 @@ class Hexagon_sf_sfsfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_sfsfsfqi_Intrinsic // @@ -528,7 +528,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_di_dididi_Intrinsic // @@ -543,7 +543,7 @@ class Hexagon_di_dididisi_Intrinsic class Hexagon_df_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_di_Intrinsic // @@ -571,21 +571,21 @@ class Hexagon_df_df_Intrinsic class Hexagon_df_dfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfdf_Intrinsic +// Hexagon_si_dfdf_Intrinsic // -class Hexagon_qi_dfdf_Intrinsic +class Hexagon_si_dfdf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfsi_Intrinsic +// Hexagon_si_dfsi_Intrinsic // -class Hexagon_qi_dfsi_Intrinsic +class Hexagon_si_dfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // // Hexagon_df_dfdfdf_Intrinsic @@ -594,7 +594,7 @@ class Hexagon_df_dfdfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_dfdfdf_Intrinsic // @@ -603,7 +603,7 @@ class Hexagon_df_dfdfdfqi_Intrinsic [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // This one below will not be generated from iset.py. @@ -624,32 +624,32 @@ Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; // // BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpeqp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtup : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; // // BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) // @@ -674,182 +674,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; // BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) // def int_hexagon_C2_bitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">; // // BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; // // BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; // // BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; // // BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; // // BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgeui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; // // BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) // def int_hexagon_C2_cmplt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">; // // BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpltu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; // // BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; // // BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; // // BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) // def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; // // BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; // // BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; // // BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) // def int_hexagon_C4_cmplte : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">; // // BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; // // BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) // def int_hexagon_C2_and : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">; // // BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) // def int_hexagon_C2_or : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">; // // BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) // def int_hexagon_C2_xor : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">; // // BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) // def int_hexagon_C2_andn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">; // // BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) // def int_hexagon_C2_not : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">; // // BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) // def int_hexagon_C2_orn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">; // // BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">; // // BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">; // // BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">; // // BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">; // // BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">; // // BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">; // // BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">; // // BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">; // // BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) // def int_hexagon_C2_pxfer_map : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; // // BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) // def int_hexagon_C2_any8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">; // // BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) // def int_hexagon_C2_all8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">; // // BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) // @@ -889,167 +889,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; // BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbeq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbeqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbeq_any : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; // // BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; // // BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpheq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpheqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; // // BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; // // BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpweq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpweqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; // // BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) // def int_hexagon_A4_boundscheck : -Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; // // BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) // def int_hexagon_A4_tlbmatch : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; // // BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) // @@ -1059,17 +1059,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; // BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) // def int_hexagon_C2_tfrrp : -Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9 : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9_not : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; // // BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) // @@ -2849,7 +2849,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; // BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) // def int_hexagon_A2_tfrpi : -Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">; // // BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) // @@ -3609,22 +3609,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; // BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpeq : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpgt : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpge : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpuo : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) // @@ -3639,7 +3639,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; // BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) // def int_hexagon_F2_sfclass : -Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; // // BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) // @@ -3666,80 +3666,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; def int_hexagon_F2_sffixupr : Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; // -// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfadd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; -// -// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfsub : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmpy : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) -// -def int_hexagon_F2_dffma_sc : -Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmax : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmin : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; -// // BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpeq : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpgt : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpge : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpuo : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) // def int_hexagon_F2_dfclass : -Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; // // BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) // @@ -3751,21 +3701,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; def int_hexagon_F2_dfimm_n : Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; // -// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupn : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) -// -def int_hexagon_F2_dffixupr : -Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; -// // BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) // def int_hexagon_F2_conv_sf2df : @@ -4494,12 +4429,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; // BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; // // BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) // @@ -4519,12 +4454,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; // BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; // // BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) // @@ -4875,3 +4810,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + +def llvm_ptr32_ty : LLVMPointerType; +def llvm_ptr64_ty : LLVMPointerType; + +// Mark locked loads as read/write to prevent any accidental reordering. +def int_hexagon_L2_loadw_locked : +Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_L4_loadd_locked : +Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +def int_hexagon_S2_storew_locked : +Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], + [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_S4_stored_locked : +Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], + [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5cdabde..110d55d 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -542,3 +542,180 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; } + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsics. +// + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics. + class PowerPC_QPX_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; +} + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Class Definitions. +// + +/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64. +class PowerPC_QPX_Load_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64 permutation. +class PowerPC_QPX_LoadPerm_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and stores a v4f64. +class PowerPC_QPX_Store_Intrinsic + : PowerPC_QPX_Intrinsic; + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Add Instructions + def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">; + def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">; + def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">; + def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">; + + // Estimate Instructions + def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">; + def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">; + def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">; + def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">; + + // Multiply Instructions + def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">; + def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">; + def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">; + def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">; + + // Multiply-add instructions + def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">; + def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">; + def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">; + def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">; + def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">; + def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">; + def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">; + def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">; + def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">; + def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">; + def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">; + def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">; + def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">; + def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">; + def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">; + def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">; + + // Select Instruction + def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">; + + // Permute Instruction + def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">; + + // Convert and Round Instructions + def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">; + def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">; + def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">; + def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">; + def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">; + def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">; + def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">; + def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">; + def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">; + def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">; + def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">; + def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">; + def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">; + def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">; + def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">; + def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">; + def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">; + + // Move Instructions + def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">; + def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">; + def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">; + def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">; + + // Compare Instructions + def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">; + def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">; + def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">; + def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">; + + // Load instructions + def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">; + def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">; + def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">; + def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">; + + def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">; + def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">; + def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">; + def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">; + def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">; + def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">; + def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">; + def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">; + + def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">; + def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">; + def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">; + def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">; + + // Store instructions + def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">; + def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">; + def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">; + def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">; + + def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">; + def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">; + def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">; + def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">; + def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">; + def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">; + + // Logical and permutation formation + def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical", + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci", + [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; +} + diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index d99c42d..5055667 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -76,6 +76,9 @@ def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < "__builtin_amdgpu_read_workdim">; diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 59ff946..60deb32 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -453,19 +453,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; } // Conversion ops @@ -1363,6 +1350,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1389,6 +1382,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ps_512 : + GCCBuiltin<"__builtin_ia32_storeaps512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_pd_512 : + GCCBuiltin<"__builtin_ia32_storeapd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; def int_x86_avx512_mask_store_ss : GCCBuiltin<"__builtin_ia32_storess_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], @@ -1572,19 +1573,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; @@ -1603,6 +1591,25 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Pack ops. @@ -1911,6 +1918,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; } // Gather ops @@ -2029,11 +2061,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_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], @@ -2063,11 +2115,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_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], @@ -2097,11 +2169,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_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], @@ -2131,11 +2223,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_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], @@ -2159,11 +2271,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_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], @@ -2187,11 +2319,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -3003,6 +3155,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + + def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -3016,12 +3193,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_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_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_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]>; @@ -3102,22 +3281,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [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_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3226,22 +3389,22 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_conflict_q_512 : GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_d_512 : GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_q_512 : GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; } // Vector blend @@ -3250,10 +3413,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -3263,6 +3442,48 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + } let TargetPrefix = "x86" in { @@ -3307,29 +3528,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem ]>; def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 256-bit @@ -3360,29 +3581,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 128-bit @@ -3413,39 +3634,243 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; } +// Compress, Expand +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_compress_ps_512 : + GCCBuiltin<"__builtin_ia32_compresssf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_512 : + GCCBuiltin<"__builtin_ia32_compressdf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_256 : + GCCBuiltin<"__builtin_ia32_compresssf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_256 : + GCCBuiltin<"__builtin_ia32_compressdf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_128 : + GCCBuiltin<"__builtin_ia32_compresssf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_128 : + GCCBuiltin<"__builtin_ia32_compressdf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_ps_512 : + GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_512 : + GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_256 : + GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_256 : + GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_128 : + GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_128 : + GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + + def int_x86_avx512_mask_compress_d_512 : + GCCBuiltin<"__builtin_ia32_compresssi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_512 : + GCCBuiltin<"__builtin_ia32_compressdi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_256 : + GCCBuiltin<"__builtin_ia32_compresssi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_256 : + GCCBuiltin<"__builtin_ia32_compressdi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_128 : + GCCBuiltin<"__builtin_ia32_compresssi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_128 : + GCCBuiltin<"__builtin_ia32_compressdi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_d_512 : + GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_512 : + GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_256 : + GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_256 : + GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_128 : + GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_128 : + GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + +// expand + def int_x86_avx512_mask_expand_ps_512 : + GCCBuiltin<"__builtin_ia32_expandsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_512 : + GCCBuiltin<"__builtin_ia32_expanddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_256 : + GCCBuiltin<"__builtin_ia32_expandsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_256 : + GCCBuiltin<"__builtin_ia32_expanddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_128 : + GCCBuiltin<"__builtin_ia32_expandsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_128 : + GCCBuiltin<"__builtin_ia32_expanddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_ps_512 : + GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_512 : + GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_256 : + GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_256 : + GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_128 : + GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_128 : + GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + + def int_x86_avx512_mask_expand_d_512 : + GCCBuiltin<"__builtin_ia32_expandsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_512 : + GCCBuiltin<"__builtin_ia32_expanddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_256 : + GCCBuiltin<"__builtin_ia32_expandsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_256 : + GCCBuiltin<"__builtin_ia32_expanddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_128 : + GCCBuiltin<"__builtin_ia32_expandsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_128 : + GCCBuiltin<"__builtin_ia32_expanddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_d_512 : + GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_512 : + GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_256 : + GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_256 : + GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_128 : + GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_128 : + GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + +} // Misc. let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i8_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 2f18782..8c04b08 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -176,8 +176,8 @@ public: } private: - LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; - void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index cb18df8..0000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index c967a6b..6c04e9d 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -37,9 +37,10 @@ class PassManagerBase { public: virtual ~PassManagerBase(); - /// add - Add a pass to the queue of passes to run. This passes ownership of + /// 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 + /// may even destroy the pass right away if it is found to be redundant. This /// implies that all passes MUST be allocated with 'new'. virtual void add(Pass *P) = 0; }; @@ -51,10 +52,6 @@ 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) override; /// run - Execute all of the passes scheduled for execution. Keep track of @@ -75,11 +72,6 @@ public: 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) override; /// run - Execute all of the passes scheduled for execution. Keep diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index ab500a1..7f7889a 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -195,6 +195,9 @@ public: /// then return NULL. Pass *findAnalysisPass(AnalysisID AID); + /// Retrieve the PassInfo for an analysis. + const PassInfo *findAnalysisPassInfo(AnalysisID AID) const; + /// Find analysis usage information for the pass P. AnalysisUsage *findAnalysisUsage(Pass *P); @@ -251,6 +254,12 @@ private: SmallVector ImmutablePasses; DenseMap AnUsageMap; + + /// Collection of PassInfo objects found via analysis IDs and in this top + /// level manager. This is used to memoize queries to the pass registry. + /// FIXME: This is an egregious hack because querying the pass registry is + /// either slow or racy. + mutable DenseMap AnalysisPassInfos; }; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index e2e4912..52db1c3 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -41,14 +41,12 @@ namespace llvm { // class PassNameParser : public PassRegistrationListener, public cl::parser { - cl::Option *Opt; public: - PassNameParser(); + PassNameParser(cl::Option &O); virtual ~PassNameParser(); - void initialize(cl::Option &O) { - Opt = &O; - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); @@ -69,7 +67,7 @@ public: // Implement the PassRegistrationListener callbacks used to populate our map // void passRegistered(const PassInfo *P) override { - if (ignorablePass(P) || !Opt) return; + if (ignorablePass(P)) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index d29512c..51b8b02 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -24,6 +24,8 @@ namespace llvm { class APInt; template class ArrayRef; class LLVMContext; +class Constant; +class ConstantAsMetadata; class MDNode; class MDString; @@ -36,6 +38,9 @@ public: /// \brief Return the given string as metadata. MDString *createString(StringRef Str); + /// \brief Return the given constant as metadata. + ConstantAsMetadata *createConstant(Constant *C); + //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// @@ -62,6 +67,9 @@ public: /// \brief Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(Constant *Lo, Constant *Hi); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def new file mode 100644 index 0000000..66589e0 --- /dev/null +++ b/include/llvm/IR/Metadata.def @@ -0,0 +1,99 @@ +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocation) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDBasicType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDDerivedTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDDerivedType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDCompositeTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompileUnit) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDNamespace) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDTemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDImportedEntity) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index a056b0d..ff8f837 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,4 +1,4 @@ -//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,11 +18,13 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/MetadataTracking.h" #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" +#include namespace llvm { class LLVMContext; @@ -38,20 +40,422 @@ enum LLVMConstants : uint32_t { /// \brief Root of the metadata hierarchy. /// /// This is a root class for typeless data in the IR. -/// -/// TODO: Detach from the Value hierarchy. -class Metadata : public Value { +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + unsigned Storage : 2; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { + MDTupleKind, + MDLocationKind, + GenericDebugNodeKind, + MDSubrangeKind, + MDEnumeratorKind, + MDBasicTypeKind, + MDDerivedTypeKind, + MDCompositeTypeKind, + MDSubroutineTypeKind, + MDFileKind, + MDCompileUnitKind, + MDSubprogramKind, + MDLexicalBlockKind, + MDLexicalBlockFileKind, + MDNamespaceKind, + MDTemplateTypeParameterKind, + MDTemplateValueParameterKind, + MDGlobalVariableKind, + MDLocalVariableKind, + MDExpressionKind, + MDObjCPropertyKind, + MDImportedEntityKind, + ConstantAsMetadataKind, + LocalAsMetadataKind, + MDStringKind + }; + protected: - Metadata(LLVMContext &Context, unsigned ID); + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + } + ~Metadata() {} + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + void dump() const; + void print(raw_ostream &OS) const; + void printAsOperand(raw_ostream &OS, bool PrintType = true, + const Module *M = nullptr) const; +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue(); + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal || - V->getValueID() == MDStringVal; + return V->getValueID() == MetadataAsValueVal; } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); }; +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + LLVMContext &Context; + uint64_t NextIndex; + SmallDenseMap, 4> UseMap; + +public: + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + LLVMContext &getContext() const { return Context; } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + static ReplaceableMetadataImpl *get(Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() {} + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template T &make(); +template struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template struct SFINAE {}; + + template + static Yes &hasDereference(SFINAE(*make()))> * = 0); + template static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference(nullptr)) == sizeof(Yes); +}; +template struct IsValidPointer { + static const bool value = std::is_base_of::value && + HasDereference::value; +}; +template struct IsValidReference { + static const bool value = std::is_base_of::value && + std::is_convertible::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template +inline typename std::enable_if::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast(MD)) + return isa(V->getValue()); + return false; +} +template +inline + typename std::enable_if::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template +inline typename std::enable_if::value, X *>::type +extract(Y &&MD) { + return cast(cast(MD)->getValue()); +} +template +inline + typename std::enable_if::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null(MD)) + return cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template +inline typename std::enable_if::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + //===----------------------------------------------------------------------===// /// \brief A single uniqued string. /// @@ -60,14 +464,13 @@ public: class MDString : public Metadata { friend class StringMapEntry; - virtual void anchor(); - MDString(const MDString &) LLVM_DELETED_FUNCTION; - - explicit MDString(LLVMContext &Context) - : Metadata(Context, Value::MDStringVal) {} + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; - /// \brief Shadow Value::getName() to prevent its use. - StringRef getName() const LLVM_DELETED_FUNCTION; + StringMapEntry *Entry; + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {} public: static MDString *get(LLVMContext &Context, StringRef Str); @@ -87,9 +490,12 @@ public: /// \brief Pointer to one byte past the end of the string. iterator end() const { return getString().end(); } + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; } }; @@ -106,7 +512,7 @@ struct AAMDNodes { bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { return TBAA || Scope || NoAlias; } /// \brief The tag for type-based alias analysis. MDNode *TBAA; @@ -137,21 +543,171 @@ struct DenseMapInfo { } }; -class MDNodeOperand; +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; -//===----------------------------------------------------------------------===// -/// \brief Tuple of metadata. + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; + +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get(); + return nullptr; + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. class MDNode : public Metadata { - MDNode(const MDNode &) LLVM_DELETED_FUNCTION; - void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - friend class MDNodeOperand; + friend class ReplaceableMetadataImpl; friend class LLVMContextImpl; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; + + unsigned NumOperands; + unsigned NumUnresolved; protected: - void *operator new(size_t Size, unsigned NumOps); + ContextAndReplaceableUses Context; - /// \brief Required by std, but never called. + void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); /// \brief Required by std, but never called. @@ -164,83 +720,188 @@ protected: llvm_unreachable("Constructor throws?"); } - /// \brief Subclass data enums. - enum { - /// FunctionLocalBit - This bit is set if this MDNode is function local. - /// This is true when it (potentially transitively) contains a reference to - /// something in a function, like an argument, basicblock, or instruction. - FunctionLocalBit = 1 << 0, + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef Ops1, ArrayRef Ops2 = None); + ~MDNode() {} - /// NotUniquedBit - This is set on MDNodes that are not uniqued because they - /// have a null operand. - NotUniquedBit = 1 << 1 - }; + void dropAllReferences(); - /// \brief FunctionLocal enums. - enum FunctionLocalness { - FL_Unknown = -1, - FL_No = 0, - FL_Yes = 1 - }; + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast(this); } - /// \brief Replace each instance of the given operand with a new value. - void replaceOperand(MDNodeOperand *Op, Value *NewVal); +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, + ArrayRef MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs); - MDNode(LLVMContext &C, unsigned ID, ArrayRef Vals, - bool isFunctionLocal); - ~MDNode() {} + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; - static MDNode *getMDNode(LLVMContext &C, ArrayRef Vals, - FunctionLocalness FL, bool Insert = true); -public: - static MDNode *get(LLVMContext &Context, ArrayRef Vals); - /// \brief Construct MDNode with an explicit function-localness. + /// \brief Deallocate a node created by getTemporary. /// - /// Don't analyze Vals; trust isFunctionLocal. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, - ArrayRef Vals, - bool isFunctionLocal); + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. + static void deleteTemporary(MDNode *N); - static MDNode *getIfExists(LLVMContext &Context, ArrayRef Vals); + LLVMContext &getContext() const { return Context.getContext(); } + + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); - /// \brief Return a temporary MDNode + /// \brief Check if node is fully resolved. /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, ArrayRef Vals); + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !Context.hasReplaceableUses(); } - /// \brief Deallocate a node created by getTemporary. + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } + + /// \brief RAUW a temporary. /// - /// The node must not have any users. - static void deleteTemporary(MDNode *N); + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + assert(!isResolved() && "Expected RAUW support"); + Context.getReplaceableUses()->replaceAllUsesWith(MD); + } - /// \brief Replace a specific operand. - void replaceOperandWith(unsigned i, Value *NewVal); + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); - /// \brief Return specified operand. - Value *getOperand(unsigned i) const LLVM_READONLY; + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template + static typename std::enable_if::value, T *>::type + replaceWithPermanent(std::unique_ptr N) { + return cast(N.release()->replaceWithPermanentImpl()); + } - /// \brief Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template + static typename std::enable_if::value, T *>::type + replaceWithUniqued(std::unique_ptr N) { + return cast(N.release()->replaceWithUniquedImpl()); + } - /// \brief Return whether MDNode is local to a function. - bool isFunctionLocal() const { - return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template + static typename std::enable_if::value, T *>::type + replaceWithDistinct(std::unique_ptr N) { + return cast(N.release()->replaceWithDistinctImpl()); } - /// \brief Return the first function-local operand's function. +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); + + void storeDistinctInContext(); + template + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + unsigned countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". /// - /// If this metadata is function-local and recursively has a function-local - /// operand, return the first such operand's parent function. Otherwise, - /// return null. getFunction() should not be used for performance- critical - /// code because it recursively visits all the MDNode's operands. - const Function *getFunction() const; + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template struct HasCachedHash; + template + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template + static void dispatchRecalculateHash(NodeTy *N, std::false_type) {} + template + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template + static void dispatchResetHash(NodeTy *N, std::false_type) {} + +public: + typedef const MDOperand *op_iterator; + typedef iterator_range op_range; + + op_iterator op_begin() const { + return const_cast(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal; + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } } /// \brief Check whether MDNode is a vtable access. @@ -250,72 +911,91 @@ public: static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); - -protected: - bool isNotUniqued() const { - return (getSubclassDataFromValue() & NotUniquedBit) != 0; - } - void setIsNotUniqued(); - - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } + static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; -/// \brief Generic metadata node. -/// -/// Generic metadata nodes, with opt-out support for uniquing. -/// -/// Although nodes are uniqued by default, \a GenericMDNode has no support for -/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing -/// collision, the uniquing bit is dropped. +/// \brief Tuple of metadata. /// -/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped). -/// TODO: Drop support for RAUW. -class GenericMDNode : public MDNode { - friend class MDNode; +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public MDNode { friend class LLVMContextImpl; + friend class MDNode; + + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } + ~MDTuple() { dropAllReferences(); } - unsigned Hash; + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); - GenericMDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, GenericMDNodeVal, Vals, isFunctionLocal), Hash(0) {} - ~GenericMDNode(); + static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, + StorageType Storage, bool ShouldCreate = true); - void dropAllReferences(); + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector(op_begin(), op_end())); + } public: /// \brief Get the hash, if any. - unsigned getHash() const { return Hash; } + unsigned getHash() const { return SubclassData32; } - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal; + static MDTuple *get(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } -}; -/// \brief Forward declaration of metadata. -/// -/// Forward declaration of metadata, in the form of a metadata node. Unlike \a -/// GenericMDNode, this class has support for RAUW and is suitable for forward -/// references. -class MDNodeFwdDecl : public MDNode { - friend class MDNode; + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Distinct); + } - MDNodeFwdDecl(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, MDNodeFwdDeclVal, Vals, isFunctionLocal) {} - ~MDNodeFwdDecl() {} + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } -public: - static bool classof(const Value *V) { - return V->getValueID() == MDNodeFwdDeclVal; + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; } }; +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::get(Context, MDs); +} +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getDistinct(Context, MDs); +} +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return MDTuple::getTemporary(Context, MDs); +} + +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// @@ -328,11 +1008,11 @@ class NamedMDNode : public ilist_node { friend struct ilist_traits; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + NamedMDNode(const NamedMDNode &) = delete; std::string Name; Module *Parent; - void *Operands; // SmallVector, 4> + void *Operands; // SmallVector void setParent(Module *M) { Parent = M; } @@ -390,6 +1070,7 @@ public: MDNode *getOperand(unsigned i) const; unsigned getNumOperands() const; void addOperand(MDNode *M); + void setOperand(unsigned I, MDNode *New); StringRef getName() const; void print(raw_ostream &ROS) const; void dump() const; diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h new file mode 100644 index 0000000..541d9b3 --- /dev/null +++ b/include/llvm/IR/MetadataTracking.h @@ -0,0 +1,99 @@ +//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Low-level functions to enable tracking of metadata that could RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATATRACKING_H +#define LLVM_IR_METADATATRACKING_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Metadata; +class MetadataAsValue; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 7fff80a..62f4194 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -33,8 +33,6 @@ class GVMaterializer; class LLVMContext; class RandomNumberGenerator; class StructType; -template struct DenseMapInfo; -template class DenseMap; template<> struct ilist_traits : public SymbolTableListTraits { @@ -150,7 +148,7 @@ public: /// The named metadata iterators. typedef NamedMDListType::iterator named_metadata_iterator; - /// The named metadata constant interators. + /// The named metadata constant iterators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; /// This enumeration defines the supported behaviors of module flags. @@ -190,16 +188,16 @@ public: ModFlagBehaviorLastVal = AppendUnique }; - /// Checks if Value represents a valid ModFlagBehavior, and stores the + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the /// converted result in MFB. - static bool isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB); + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; - Value *Val; - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) - : Behavior(B), Key(K), Val(V) {} + Metadata *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} }; /// @} @@ -219,9 +217,8 @@ private: Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - // Allow lazy initialization in const method. - mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -251,6 +248,12 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// \brief Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). const std::string &getDataLayoutStr() const { return DataLayoutStr; } @@ -270,10 +273,16 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - /// Get the RandomNumberGenerator for this module. The RNG can be - /// seeded via -rng-seed= and is salted with the ModuleID. - /// The returned RNG should not be shared across threads. - RandomNumberGenerator &getRNG() const; + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed= and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + RandomNumberGenerator *createRNG(const Pass* P) const; /// @} /// @name Module Level Mutators @@ -327,6 +336,8 @@ public: /// name. StructType *getTypeByName(StringRef Name) const; + std::vector getIdentifiedStructTypes() const; + /// @} /// @name Function Accessors /// @{ @@ -441,7 +452,7 @@ public: /// Return the corresponding value if Key appears in module flags, otherwise /// return null. - Value *getModuleFlag(StringRef Key) const; + Metadata *getModuleFlag(StringRef Key) const; /// Returns the NamedMDNode in the module that represents module-level flags. /// This method returns null if there are no module-level flags. @@ -454,7 +465,8 @@ public: /// Add a module-level flag to the module-level flags metadata. It will create /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -483,7 +495,7 @@ public: std::error_code materialize(GlobalValue *GV); /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized - /// lazily. If !isDematerializable(), this method is a noop. + /// lazily. If !isDematerializable(), this method is a no-op. void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. @@ -618,6 +630,15 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 0933f21..46935ce 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -34,12 +34,12 @@ class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself // instantiated. - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; - Operator() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + Operator() = delete; protected: - // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. ~Operator(); @@ -504,6 +504,20 @@ public: } }; +class BitCastOperator + : public ConcreteOperator { + friend class BitCastInst; + friend class ConstantExpr; + +public: + Type *getSrcTy() const { + return getOperand(0)->getType(); + } + + Type *getDestTy() const { + return getType(); + } +}; } // End llvm namespace diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 45985e1..c92e7c9 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -43,6 +43,9 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManagerInternal.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/type_traits.h" #include #include @@ -91,9 +94,12 @@ public: } /// \brief Mark a particular pass as preserved, adding it to the set. - template void preserve() { + template void preserve() { preserve(PassT::ID()); } + + /// \brief Mark an abstract PassID as preserved, adding it to the set. + void preserve(void *PassID) { if (!areAllPreserved()) - PreservedPassIDs.insert(PassT::ID()); + PreservedPassIDs.insert(PassID); } /// \brief Intersect this set with another in place. @@ -140,408 +146,115 @@ public: PreservedPassIDs.count(PassID); } + /// \brief Test whether all passes are preserved. + /// + /// This is used primarily to optimize for the case of no changes which will + /// common in many scenarios. + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + private: // Note that this must not be -1 or -2 as those are already used by the // SmallPtrSet. static const uintptr_t AllPassesID = (intptr_t)(-3); - bool areAllPreserved() const { - return PreservedPassIDs.count((void *)AllPassesID); - } - SmallPtrSet PreservedPassIDs; }; -/// \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() {} - - /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManagerT. -template -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); +// Forward declare the analysis manager template. +template class AnalysisManager; -public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief A template wrapper used to implement the polymorphic API. +/// \brief Manages a sequence of passes over units of IR. /// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT. It requires the pass to be a copyable object. When the -/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. -template ::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR, AM); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Abstract concept of an analysis result. +/// A pass manager contains a sequence of passes to run over units of IR. It is +/// itself a valid pass over that unit of IR, and when over some given IR will +/// run each pass in sequence. This is the primary and most basic building +/// block of a pass pipeline. /// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// This method also receives a set of preserved analyses which can be used - /// to avoid invalidation because the pass which changed the underlying IR - /// took care to update or preserve the analysis result in some way. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template class ResultHasInvalidateMethod { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); - +/// If it is run with an \c AnalysisManager argument, it will propagate +/// that analysis manager to each pass it runs, as well as calling the analysis +/// manager's invalidation routine with the PreservedAnalyses of each pass it +/// runs. +template class PassManager { public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template ::Value> -struct AnalysisResultModel; - -/// \brief Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { - return !PA.preserved(PassT::ID()); - } - - ResultT Result; -}; - -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { + Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } - /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { - return Result.invalidate(IR, PA); - } + /// \brief Run all of the passes in this manager over the IR. + PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM = nullptr) { + PreservedAnalyses PA = PreservedAnalyses::all(); - ResultT Result; -}; + if (DebugLogging) + dbgs() << "Starting pass manager run.\n"; -/// \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() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) = 0; -}; + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + if (DebugLogging) + dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; -/// \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 ::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // 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. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) override { - return make_unique(Pass.run(IR, AM)); - } + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); - PassT Pass; -}; + // If we have an active analysis manager at this level we want to ensure + // we update it as each pass runs and potentially invalidates analyses. + // We also update the preserved set of analyses based on what analyses we + // have already handled the invalidation for here and don't need to + // invalidate when finished. + if (AM) + PassPA = AM->invalidate(IR, std::move(PassPA)); -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // 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. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *) override { - return make_unique(Pass.run(IR)); - } - - PassT Pass; -}; + // Finally, we intersect the final preserved analyses to compute the + // aggregate preserved set for this pass manager. + PA.intersect(std::move(PassPA)); -} // End namespace detail + // FIXME: Historically, the pass managers all called the LLVM context's + // yield function here. We don't have a generic way to acquire the + // context and it isn't yet clear what the right pattern is for yielding + // in the new pass manager so it is currently omitted. + //IR.getContext().yield(); + } -class ModuleAnalysisManager; + if (DebugLogging) + dbgs() << "Finished pass manager run.\n"; -class ModulePassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModulePassManager() {} - ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - ModulePassManager &operator=(ModulePassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; + return PA; } - /// \brief Run all of the module passes in this module pass manager over - /// a module. - /// - /// This method should only be called for a single module as there is the - /// expectation that the lifetime of a pass is bounded to that of a module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); - - template void addPass(ModulePassT Pass) { - Passes.emplace_back(new ModulePassModel(std::move(Pass))); + template void addPass(PassT Pass) { + typedef detail::PassModel PassModelT; + Passes.emplace_back(new PassModelT(std::move(Pass))); } - static StringRef name() { return "ModulePassManager"; } + static StringRef name() { return "PassManager"; } 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( - std::move(Pass)) {} - }; - - ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; - ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + typedef detail::PassConcept PassConceptT; - std::vector> Passes; -}; + PassManager(const PassManager &) = delete; + PassManager &operator=(const PassManager &) = delete; -class FunctionAnalysisManager; + std::vector> Passes; -class FunctionPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionPassManager() {} - FunctionPassManager(FunctionPassManager &&Arg) - : Passes(std::move(Arg.Passes)) {} - FunctionPassManager &operator=(FunctionPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - template void addPass(FunctionPassT Pass) { - Passes.emplace_back(new FunctionPassModel(std::move(Pass))); - } - - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); - - static StringRef name() { return "FunctionPassManager"; } + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; +}; -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( - std::move(Pass)) {} - }; +/// \brief Convenience typedef for a pass manager over modules. +typedef PassManager ModulePassManager; - FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - FunctionPassManager & - operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; +/// \brief Convenience typedef for a pass manager over functions. +typedef PassManager FunctionPassManager; namespace detail { @@ -556,19 +269,25 @@ namespace detail { /// - invalidateImpl /// /// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. template class AnalysisManagerBase { DerivedT *derived_this() { return static_cast(this); } const DerivedT *derived_this() const { return static_cast(this); } - AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase(const AnalysisManagerBase &) = delete; AnalysisManagerBase & - operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + operator=(const AnalysisManagerBase &) = delete; protected: typedef detail::AnalysisResultConcept ResultConceptT; - typedef detail::AnalysisPassConcept PassConceptT; + typedef detail::AnalysisPassConcept PassConceptT; // FIXME: Provide template aliases for the models when we're using C++11 in // a mode supporting them. @@ -588,7 +307,7 @@ public: /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template typename PassT::Result &getResult(IRUnitT IR) { + template typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -605,7 +324,7 @@ public: /// /// \returns null if there is no cached result. template - typename PassT::Result *getCachedResult(IRUnitT IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -627,25 +346,28 @@ public: template void registerPass(PassT Pass) { assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - typedef detail::AnalysisPassModel PassModelT; + typedef detail::AnalysisPassModel PassModelT; AnalysisPasses[PassT::ID()].reset(new PassModelT(std::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) { + template void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { - derived_this()->invalidateImpl(IR, PA); + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); } protected: @@ -675,108 +397,153 @@ private: } // End namespace detail -/// \brief A module analysis pass manager with lazy running and caching of +/// \brief A generic analysis pass manager with lazy running and caching of /// results. -class ModuleAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManager() {} - ModuleAnalysisManager(ModuleAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} - ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); - return *this; - } - -private: - ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - ModuleAnalysisManager & - operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a module pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Module *M); - - /// \brief Get a cached module pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; - - /// \brief Invalidate a module pass result. - void invalidateImpl(void *PassID, Module *M); - - /// \brief Invalidate results across a module. - void invalidateImpl(Module *M, const PreservedAnalyses &PA); - - /// \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 A function analysis manager to coordinate and cache analyses run over -/// a module. -class FunctionAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase - BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +template +class AnalysisManager + : public detail::AnalysisManagerBase, IRUnitT> { + friend class detail::AnalysisManagerBase, IRUnitT>; + typedef detail::AnalysisManagerBase, IRUnitT> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManager() {} - FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast(Arg))), - FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} - FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast(RHS))); - FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } - /// \brief Clear the function analysis result cache. + /// \brief Clear the analysis result cache. /// - /// This routine allows cleaning up when the set of functions itself has + /// This routine allows cleaning up when the set of IR units itself has /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } private: - FunctionAnalysisManager(const FunctionAnalysisManager &) - LLVM_DELETED_FUNCTION; - FunctionAnalysisManager & - operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; + + /// \brief Get an analysis result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( + std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(PassID); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; + ResultList.emplace_back(PassID, P.run(IR, this)); + RI->second = std::prev(ResultList.end()); + } - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Function *F); + return *RI->second->second; + } - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; + /// \brief Get a cached analysis result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; + } /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + void invalidateImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + if (RI == AnalysisResults.end()) + return; + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + AnalysisResultLists[&IR].erase(RI->second); + AnalysisResults.erase(RI); + } /// \brief Invalidate the results for a function.. - void invalidateImpl(Function *F, const PreservedAnalyses &PA); + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return std::move(PA); + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " + << IR.getName() << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector InvalidatedPassIDs; + AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + void *PassID = I->first; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->second->invalidate(IR, PA)) { + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(PassID); + } + while (!InvalidatedPassIDs.empty()) + AnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); + if (ResultsList.empty()) + AnalysisResultLists.erase(&IR); + + return std::move(PA); + } /// \brief List of function analysis pass IDs and associated concept pointers. /// @@ -784,30 +551,37 @@ private: /// 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>>> - FunctionAnalysisResultListT; + void *, std::unique_ptr>>> + AnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - FunctionAnalysisResultListMapT; + typedef DenseMap AnalysisResultListMapT; /// \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; + AnalysisResultListMapT AnalysisResultLists; /// \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; + typedef DenseMap, + typename AnalysisResultListT::iterator> AnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. - FunctionAnalysisResultMapT FunctionAnalysisResults; + AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; +/// \brief Convenience typedef for the Module analysis manager. +typedef AnalysisManager ModuleAnalysisManager; + +/// \brief Convenience typedef for the Function analysis manager. +typedef AnalysisManager FunctionAnalysisManager; + /// \brief A module analysis which acts as a proxy for a function analysis /// manager. /// @@ -822,6 +596,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -846,7 +622,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -884,7 +660,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -920,7 +696,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -928,6 +704,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -946,7 +724,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(Function *) { return Result(*MAM); } + Result run(Function &) { return Result(*MAM); } private: static char PassID; @@ -962,6 +740,20 @@ private: /// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. +/// +/// Function passes run within this adaptor can rely on having exclusive access +/// to the function they are run over. They should not read or modify any other +/// functions! Other threads or systems may be manipulating other functions in +/// the module, and so their state should never be relied on. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. +/// +/// Function passes can also read the module containing the function, but they +/// should not modify that module outside of the use lists of various globals. +/// For example, a function pass is not permitted to add functions to the +/// module. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. template class ModuleToFunctionPassAdaptor { public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) @@ -972,7 +764,8 @@ public: : Pass(Arg.Pass) {} ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + friend void swap(ModuleToFunctionPassAdaptor &LHS, + ModuleToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -982,21 +775,26 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(I, FAM); + for (Function &F : M) { + if (F.isDeclaration()) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. + // directly handle the function analysis manager's invalidation here and + // update our preserved set to reflect that these have already been + // handled. if (FAM) - FAM->invalidate(I, PassPA); + PassPA = FAM->invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -1025,6 +823,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(ModuleToFunctionPassAdaptor(std::move(Pass))); } +/// \brief A template utility pass to force an analysis result to be available. +/// +/// This is a no-op pass which simply forces a specific analysis pass's result +/// to be available when it is run. +template struct RequireAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + (void)AM->template getResult(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "RequireAnalysisPass"; } +}; + +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template struct InvalidateAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "InvalidateAnalysisPass"; } +}; + +/// \brief A utility pass that does nothing but preserves no analyses. +/// +/// As a consequence fo not preserving any analyses, this pass will force all +/// analysis passes to be re-run to produce fresh results if any are needed. +struct InvalidateAllAnalysesPass { + /// \brief Run this pass over some unit of IR. + template PreservedAnalyses run(IRUnitT &Arg) { + return PreservedAnalyses::none(); + } + + static StringRef name() { return "InvalidateAllAnalysesPass"; } +}; + } #endif diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h new file mode 100644 index 0000000..297f5f4 --- /dev/null +++ b/include/llvm/IR/PassManagerInternal.h @@ -0,0 +1,349 @@ +//===- PassManager internal APIs and implementation details -----*- 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 provides internal APIs and implementation details used by the +/// pass management interfaces exposed in PassManager.h. To understand more +/// context of why these particular interfaces are needed, see that header +/// file. None of these APIs should be used elsewhere. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSMANAGERINTERNAL_H +#define LLVM_IR_PASSMANAGERINTERNAL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +template class AnalysisManager; +class PreservedAnalyses; + +/// \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() {} + + /// \brief The polymorphic API which runs the pass over a given IR entity. + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManager. +template +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template *)> + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManager*, we pass it +/// along. +template ::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \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() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template ::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { + return Result.invalidate(IR, PA); + } + + 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() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 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 ::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // 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. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) override { + return make_unique(Pass.run(IR, AM)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // 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. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *) override { + return make_unique(Pass.run(IR)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +} // End namespace detail +} + +#endif diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 4783062..f94e105 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -38,55 +38,58 @@ namespace llvm { namespace PatternMatch { -template -bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); +template bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); } - -template -struct OneUse_match { +template struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; -template -inline OneUse_match m_OneUse(const T &SubPattern) { return SubPattern; } - +template inline OneUse_match m_OneUse(const T &SubPattern) { + return SubPattern; +} -template -struct class_match { - template - bool match(ITy *V) { return isa(V); } +template struct class_match { + template bool match(ITy *V) { return isa(V); } }; -/// m_Value() - Match an arbitrary value and ignore it. +/// \brief Match an arbitrary value and ignore it. inline class_match m_Value() { return class_match(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. + +/// \brief Match an arbitrary binary operation and ignore it. +inline class_match m_BinOp() { + return class_match(); +} + +/// \brief Matches any compare instruction and ignore it. +inline class_match m_Cmp() { return class_match(); } + +/// \brief Match an arbitrary ConstantInt and ignore it. inline class_match m_ConstantInt() { return class_match(); } -/// m_Undef() - Match an arbitrary undef constant. + +/// \brief Match an arbitrary undef constant. inline class_match m_Undef() { return class_match(); } +/// \brief Match an arbitrary Constant and ignore it. inline class_match m_Constant() { return class_match(); } /// Matching combinators -template -struct match_combine_or { +template struct match_combine_or { LTy L; RTy R; - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) @@ -95,15 +98,13 @@ struct match_combine_or { } }; -template -struct match_combine_and { +template struct match_combine_and { LTy L; RTy R; - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; @@ -112,46 +113,44 @@ struct match_combine_and { }; /// Combine two pattern matchers matching L || R -template +template inline match_combine_or m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or(L, R); } /// Combine two pattern matchers matching L && R -template +template inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and(L, R); } struct match_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNullValue(); return false; } }; -/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNegativeZeroValue(); return false; } }; -/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_combine_or m_AnyZero() { @@ -161,16 +160,14 @@ inline match_combine_or m_AnyZero() { struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CI = dyn_cast(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) { + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) { Res = &CI->getValue(); return true; } @@ -178,16 +175,13 @@ struct apint_match { } }; -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - -template -struct constantint_match { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) { +template struct constantint_match { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast(Val); @@ -200,45 +194,39 @@ struct constantint_match { } }; -/// m_ConstantInt - Match a ConstantInt with a specific value. -template -inline constantint_match m_ConstantInt() { +/// \brief Match a ConstantInt with a specific value. +template inline constantint_match m_ConstantInt() { return constantint_match(); } -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template -struct cst_pred_ty : public Predicate { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate. +template struct cst_pred_ty : public Predicate { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (const ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (const auto *CI = dyn_cast_or_null(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template -struct api_pred_ty : public Predicate { +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APInt. +template struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; @@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate { } }; - struct is_one { bool isValue(const APInt &C) { return C == 1; } }; -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +/// \brief Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty m_One() { return cst_pred_ty(); } inline api_pred_ty m_One(const APInt *&V) { return V; } @@ -261,34 +248,43 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty m_AllOnes() {return cst_pred_ty();} +/// \brief Match an integer or vector with all bits set to true. +inline cst_pred_ty m_AllOnes() { + return cst_pred_ty(); +} inline api_pred_ty m_AllOnes(const APInt *&V) { return V; } struct is_sign_bit { bool isValue(const APInt &C) { return C.isSignBit(); } }; -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty m_SignBit() {return cst_pred_ty();} +/// \brief Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty m_SignBit() { + return cst_pred_ty(); +} inline api_pred_ty m_SignBit(const APInt *&V) { return V; } struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; -/// m_Power2() - Match an integer or vector power of 2. +/// \brief Match an integer or vector power of 2. inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } -template -struct bind_ty { +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } +inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } + +template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} - template - bool match(ITy *V) { - if (Class *CV = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CV = dyn_cast(V)) { VR = CV; return true; } @@ -296,64 +292,62 @@ struct bind_ty { } }; -/// m_Value - Match a value, capturing it if we match. +/// \brief Match a value, capturing it if we match. inline bind_ty m_Value(Value *&V) { return V; } -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +/// \brief Match a binary operator, capturing it if we match. +inline bind_ty m_BinOp(BinaryOperator *&I) { return I; } + +/// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } -/// m_Constant - Match a Constant, capturing the value if we match. +/// \brief Match a Constant, capturing the value if we match. inline bind_ty m_Constant(Constant *&C) { return C; } -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +/// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty m_ConstantFP(ConstantFP *&C) { return C; } -/// specificval_ty - Match a specified Value*. +/// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} - template - bool match(ITy *V) { - return V == Val; - } + template bool match(ITy *V) { return V == Val; } }; -/// m_Specific - Match if we have a specific specified value. +/// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// Match a specified floating point value or vector of all elements of that -/// value. +/// \brief Match a specified floating point value or vector of all elements of +/// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} - template - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CFP = dyn_cast(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantFP *CFP = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CFP = dyn_cast_or_null(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; -/// Match a specific floating point value or vector with all elements equal to -/// the value. +/// \brief Match a specific floating point value or vector with all elements +/// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// Match a float 1.0 or vector with all elements equal to 1.0. +/// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - template - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CV = dyn_cast(V)) if (CV->getBitWidth() <= 64) { VR = CV->getZExtValue(); return true; @@ -362,14 +356,14 @@ struct bind_const_intval_ty { } }; -/// Match a specified integer value or vector of all elements of that value. +/// \brief Match a specified integer value or vector of all elements of that +// value. struct specific_intval { uint64_t Val; specific_intval(uint64_t V) : Val(V) {} - template - bool match(ITy *V) { - ConstantInt *CI = dyn_cast(V); + template bool match(ITy *V) { + const auto *CI = dyn_cast(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) CI = dyn_cast_or_null(C->getSplatValue()); @@ -381,156 +375,177 @@ struct specific_intval { } }; -/// Match a specific integer value or vector with all elements equal to the -/// value. +/// \brief Match a specific integer value or vector with all elements equal to +/// the value. inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. +/// \brief Match a ConstantInt and bind to its value. This does not match +/// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } //===----------------------------------------------------------------------===// +// Matcher for any binary operator. +// +template struct AnyBinaryOp_match { + LHS_t L; + RHS_t R; + + AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + return false; + } +}; + +template +inline AnyBinaryOp_match m_BinOp(const LHS &L, const RHS &R) { + return AnyBinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template +template struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -template -inline BinaryOp_match -m_Add(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Add(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FAdd(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FAdd(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Sub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Sub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FSub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FSub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Mul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Mul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FMul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FMul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_UDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_UDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_URem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_And(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_And(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Or(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Or(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Xor(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Xor(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Shl(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Shl(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_LShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_LShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_AShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template +template struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) + : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (OverflowingBinaryOperator *Op = dyn_cast(V)) { + template bool match(OpTy *V) { + if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && @@ -614,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // -template +template struct BinOp2_match { LHS_t L; RHS_t R; BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opc1 || V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -/// m_Shr - Matches LShr or AShr. -template +/// \brief Matches LShr or AShr. +template inline BinOp2_match m_Shr(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_LogicalShift - Matches LShr or Shl. -template +/// \brief Matches LShr or Shl. +template inline BinOp2_match m_LogicalShift(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_IDiv - Matches UDiv and SDiv. -template +/// \brief Matches UDiv and SDiv. +template inline BinOp2_match m_IDiv(const LHS &L, const RHS &R) { return BinOp2_match(L, R); @@ -659,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // -template -struct Exact_match { +template struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (PossiblyExactOperator *PEO = dyn_cast(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; -template -inline Exact_match m_Exact(const T &SubPattern) { return SubPattern; } +template inline Exact_match m_Exact(const T &SubPattern) { + return SubPattern; +} //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // -template +template struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} + : Predicate(Pred), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (Class *I = dyn_cast(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); @@ -700,123 +712,114 @@ struct CmpClass_match { } }; -template +template +inline CmpClass_match +m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template inline CmpClass_match m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } -template +template inline CmpClass_match m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // -template +template struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; -template -inline SelectClass_match -m_Select(const Cond &C, const LHS &L, const RHS &R) { +template +inline SelectClass_match m_Select(const Cond &C, const LHS &L, + const RHS &R) { return SelectClass_match(C, L, R); } -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template -inline SelectClass_match, constantint_match > +/// \brief This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template +inline SelectClass_match, constantint_match> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt(), m_ConstantInt()); } - //===----------------------------------------------------------------------===// // Matchers for CastInst classes // -template -struct CastClass_match { +template struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; -/// m_BitCast -template -inline CastClass_match -m_BitCast(const OpTy &Op) { +/// \brief Matches BitCast. +template +inline CastClass_match m_BitCast(const OpTy &Op) { return CastClass_match(Op); } -/// m_PtrToInt -template -inline CastClass_match -m_PtrToInt(const OpTy &Op) { +/// \brief Matches PtrToInt. +template +inline CastClass_match m_PtrToInt(const OpTy &Op) { return CastClass_match(Op); } -/// m_Trunc -template -inline CastClass_match -m_Trunc(const OpTy &Op) { +/// \brief Matches Trunc. +template +inline CastClass_match m_Trunc(const OpTy &Op) { return CastClass_match(Op); } -/// m_SExt -template -inline CastClass_match -m_SExt(const OpTy &Op) { +/// \brief Matches SExt. +template +inline CastClass_match m_SExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_ZExt -template -inline CastClass_match -m_ZExt(const OpTy &Op) { +/// \brief Matches ZExt. +template +inline CastClass_match m_ZExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_UIToFP -template -inline CastClass_match -m_UIToFP(const OpTy &Op) { +/// \brief Matches UIToFP. +template +inline CastClass_match m_UIToFP(const OpTy &Op) { return CastClass_match(Op); } -/// m_SIToFP -template -inline CastClass_match -m_SIToFP(const OpTy &Op) { +/// \brief Matches SIToFP. +template +inline CastClass_match m_SIToFP(const OpTy &Op) { return CastClass_match(Op); } @@ -824,46 +827,41 @@ m_SIToFP(const OpTy &Op) { // Matchers for unary operators // -template -struct not_match { +template struct not_match { LHS_t L; not_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Xor) return matchIfNot(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNot(Value *LHS, Value *RHS) { return (isa(RHS) || isa(RHS) || // FIXME: Remove CV. isa(RHS)) && - cast(RHS)->isAllOnesValue() && - L.match(LHS); + cast(RHS)->isAllOnesValue() && L.match(LHS); } }; -template -inline not_match m_Not(const LHS &L) { return L; } +template inline not_match m_Not(const LHS &L) { return L; } - -template -struct neg_match { +template struct neg_match { LHS_t L; neg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Sub) return matchIfNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNeg(Value *LHS, Value *RHS) { return ((isa(LHS) && cast(LHS)->isZero()) || @@ -872,36 +870,33 @@ private: } }; -/// m_Neg - Match an integer negate. -template -inline neg_match m_Neg(const LHS &L) { return L; } - +/// \brief Match an integer negate. +template inline neg_match m_Neg(const LHS &L) { return L; } -template -struct fneg_match { +template struct fneg_match { LHS_t L; fneg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::FSub) return matchIfFNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast(LHS)) + if (const auto *C = dyn_cast(LHS)) return C->isNegativeZeroValue() && L.match(RHS); return false; } }; -/// m_FNeg - Match a floating point negate. -template -inline fneg_match m_FNeg(const LHS &L) { return L; } - +/// \brief Match a floating point negate. +template inline fneg_match m_FNeg(const LHS &L) { + return L; +} //===----------------------------------------------------------------------===// // Matchers for control flow. @@ -909,13 +904,10 @@ inline fneg_match m_FNeg(const LHS &L) { return L; } struct br_match { BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } + br_match(BasicBlock *&Succ) : Succ(Succ) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); return true; @@ -926,17 +918,14 @@ struct br_match { inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } -template -struct brc_match { +template struct brc_match { Cond_t Cond; BasicBlock *&T, *&F; brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } + : Cond(C), T(t), F(f) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) { T = BI->getSuccessor(0); F = BI->getSuccessor(1); @@ -946,31 +935,28 @@ struct brc_match { } }; -template +template inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match(C, T, F); } - //===----------------------------------------------------------------------===// // Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). // -template +template struct MaxMin_match { LHS_t L; RHS_t R; - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} + MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast(V); + auto *SI = dyn_cast(V); if (!SI) return false; - CmpInst_t *Cmp = dyn_cast(SI->getCondition()); + auto *Cmp = dyn_cast(SI->getCondition()); if (!Cmp) return false; // At this point we have a select conditioned on a comparison. Check that @@ -982,8 +968,8 @@ struct MaxMin_match { if ((TrueVal != LHS || FalseVal != RHS) && (TrueVal != RHS || FalseVal != LHS)) return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); + typename CmpInst_t::Predicate Pred = + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -992,83 +978,83 @@ struct MaxMin_match { } }; -/// smax_pred_ty - Helper class for identifying signed max predicates. +/// \brief Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// smin_pred_ty - Helper class for identifying signed min predicates. +/// \brief Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// umax_pred_ty - Helper class for identifying unsigned max predicates. +/// \brief Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// umin_pred_ty - Helper class for identifying unsigned min predicates. +/// \brief Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. +/// \brief Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. +/// \brief Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. +/// \brief Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. +/// \brief Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; } }; -template -inline MaxMin_match -m_SMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_SMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1081,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMax(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1096,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1111,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(L, R); @@ -1126,40 +1112,37 @@ m_UnordFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMin(const LHS &L, const RHS &R) { return MaxMin_match(L, R); } -template -struct Argument_match { +template struct Argument_match { unsigned OpI; Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { CallSite CS(V); return CS.isCall() && Val.match(CS.getArgument(OpI)); } }; -/// Match an argument -template +/// \brief Match an argument. +template inline Argument_match m_Argument(const Opnd_t &Op) { return Argument_match(OpI, Op); } -/// Intrinsic matchers. +/// \brief Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template - bool match(OpTy *V) { - if (const CallInst *CI = dyn_cast(V)) - if (const Function *F = CI->getCalledFunction()) + template bool match(OpTy *V) { + if (const auto *CI = dyn_cast(V)) + if (const auto *F = CI->getCalledFunction()) return F->getIntrinsicID() == ID; return false; } @@ -1172,73 +1155,71 @@ struct IntrinsicID_match { template struct m_Intrinsic_Ty; -template -struct m_Intrinsic_Ty { - typedef match_combine_and > Ty; + typename T9 = void, typename T10 = void> +struct m_Intrinsic_Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and> Ty; }; -template -struct m_Intrinsic_Ty { - typedef match_combine_and::Ty, - Argument_match > Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and::Ty, Argument_match> + Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; -/// Match intrinsic calls like this: -/// m_Intrinsic(m_Value(X)) -template -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } +/// \brief Match intrinsic calls like this: +/// m_Intrinsic(m_Value(X)) +template inline IntrinsicID_match m_Intrinsic() { + return IntrinsicID_match(IntrID); +} -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic(), m_Argument<0>(Op0)); } -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, + const T1 &Op1) { return m_CombineAnd(m_Intrinsic(Op0), m_Argument<1>(Op1)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic(Op0, Op1), m_Argument<2>(Op2)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2), m_Argument<3>(Op3)); } -// Helper intrinsic matching specializations -template -inline typename m_Intrinsic_Ty::Ty -m_BSwap(const Opnd0 &Op0) { +// Helper intrinsic matching specializations. +template +inline typename m_Intrinsic_Ty::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic(Op0); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMin(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMin(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMax(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMax(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h new file mode 100644 index 0000000..38720ed --- /dev/null +++ b/include/llvm/IR/Statepoint.h @@ -0,0 +1,298 @@ +//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions and a wrapper class analogous to +// CallSite for accessing the fields of gc.statepoint, gc.relocate, and +// gc.result intrinsics +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_IR_STATEPOINT_H +#define __LLVM_IR_STATEPOINT_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class GCRelocateOperands; +class ImmutableStatepoint; + +bool isStatepoint(const ImmutableCallSite &CS); +bool isStatepoint(const Value *inst); +bool isStatepoint(const Value &inst); + +bool isGCRelocate(const Value *inst); +bool isGCRelocate(const ImmutableCallSite &CS); + +bool isGCResult(const Value *inst); +bool isGCResult(const ImmutableCallSite &CS); + +/// Analogous to CallSiteBase, this provides most of the actual +/// functionality for Statepoint and ImmutableStatepoint. It is +/// templatized to allow easily specializing of const and non-const +/// concrete subtypes. This is structured analogous to CallSite +/// rather than the IntrinsicInst.h helpers since we want to support +/// invokable statepoints in the near future. +/// TODO: This does not currently allow the if(Statepoint S = ...) +/// idiom used with CallSites. Consider refactoring to support. +template +class StatepointBase { + CallSiteTy StatepointCS; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + + protected: + explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { + assert(isStatepoint(I)); + } + explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { + assert(isStatepoint(CS)); + } + + public: + typedef typename CallSiteTy::arg_iterator arg_iterator; + + /// Return the underlying CallSite. + CallSiteTy getCallSite() { + return StatepointCS; + } + + /// Return the value actually being called or invoked. + ValueTy *actualCallee() { + return StatepointCS.getArgument(0); + } + /// Number of arguments to be passed to the actual callee. + int numCallArgs() { + return cast(StatepointCS.getArgument(1))->getZExtValue(); + } + /// Number of additional arguments excluding those intended + /// for garbage collection. + int numTotalVMSArgs() { + return cast(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + } + + typename CallSiteTy::arg_iterator call_args_begin() { + // 3 = callTarget, #callArgs, flag + int Offset = 3; + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator call_args_end() { + int Offset = 3 + numCallArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for call arguments + iterator_range call_args() { + return iterator_range(call_args_begin(), call_args_end()); + } + + typename CallSiteTy::arg_iterator vm_state_begin() { + return call_args_end(); + } + typename CallSiteTy::arg_iterator vm_state_end() { + int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for vm state arguments + iterator_range vm_state_args() { + return iterator_range(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { + // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, + // 1st_#stack, 1st_#local, 1st_#monitor + return vm_state_begin() + 6; + } + + typename CallSiteTy::arg_iterator gc_args_begin() { + return vm_state_end(); + } + typename CallSiteTy::arg_iterator gc_args_end() { + return StatepointCS.arg_end(); + } + + /// range adapter for gc arguments + iterator_range gc_args() { + return iterator_range(gc_args_begin(), gc_args_end()); + } + + /// Get list of all gc reloactes linked to this statepoint + /// May contain several relocations for the same base/derived pair. + /// For example this could happen due to relocations on unwinding + /// path of invoke. + std::vector getRelocates(ImmutableStatepoint &IS); + +#ifndef NDEBUG + /// Asserts if this statepoint is malformed. Common cases for failure + /// include incorrect length prefixes for variable length sections or + /// illegal values for parameters. + void verify() { + assert(numCallArgs() >= 0 && + "number of arguments to actually callee can't be negative"); + + // The internal asserts in the iterator accessors do the rest. + (void)call_args_begin(); + (void)call_args_end(); + (void)vm_state_begin(); + (void)vm_state_end(); + (void)gc_args_begin(); + (void)gc_args_end(); + } +#endif +}; + +/// A specialization of it's base class for read only access +/// to a gc.statepoint. +class ImmutableStatepoint + : public StatepointBase { + typedef StatepointBase + Base; + +public: + explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} + explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} +}; + +/// A specialization of it's base class for read-write access +/// to a gc.statepoint. +class Statepoint : public StatepointBase { + typedef StatepointBase Base; + +public: + explicit Statepoint(Instruction *I) : Base(I) {} + explicit Statepoint(CallSite CS) : Base(CS) {} +}; + +/// Wraps a call to a gc.relocate and provides access to it's operands. +/// TODO: This should likely be refactored to resememble the wrappers in +/// InstrinsicInst.h. +class GCRelocateOperands { + ImmutableCallSite RelocateCS; + + public: + GCRelocateOperands(const User* U) : RelocateCS(U) { + assert(isGCRelocate(U)); + } + GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { + assert(isGCRelocate(inst)); + } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { + assert(isGCRelocate(CS)); + } + + /// Return true if this relocate is tied to the invoke statepoint. + /// This includes relocates which are on the unwinding path. + bool isTiedToInvoke() const { + const Value *Token = RelocateCS.getArgument(0); + + return isa(Token) || + isa(Token); + } + + /// Get enclosed relocate intrinsic + ImmutableCallSite getUnderlyingCallSite() { + return RelocateCS; + } + + /// The statepoint with which this gc.relocate is associated. + const Instruction *statepoint() { + const Value *token = RelocateCS.getArgument(0); + + // This takes care both of relocates for call statepoints and relocates + // on normal path of invoke statepoint. + if (!isa(token)) { + return cast(token); + } + + // This relocate is on exceptional path of an invoke statepoint + const BasicBlock *invokeBB = + cast(token)->getParent()->getUniquePredecessor(); + + assert(invokeBB && "safepoints should have unique landingpads"); + assert(invokeBB->getTerminator() && "safepoint block should be well formed"); + assert(isStatepoint(invokeBB->getTerminator())); + + return invokeBB->getTerminator(); + } + /// The index into the associate statepoint's argument list + /// which contains the base pointer of the pointer whose + /// relocation this gc.relocate describes. + unsigned basePtrIndex() { + return cast(RelocateCS.getArgument(1))->getZExtValue(); + } + /// The index into the associate statepoint's argument list which + /// contains the pointer whose relocation this gc.relocate describes. + unsigned derivedPtrIndex() { + return cast(RelocateCS.getArgument(2))->getZExtValue(); + } + Value *basePtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + basePtrIndex()); + } + Value *derivedPtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + derivedPtrIndex()); + } +}; + +template +std::vector + StatepointBase:: + getRelocates(ImmutableStatepoint &IS) { + + std::vector res; + + ImmutableCallSite StatepointCS = IS.getCallSite(); + + // Search for relocated pointers. Note that working backwards from the + // gc_relocates ensures that we only get pairs which are actually relocated + // and used after the statepoint. + for (const User *U : StatepointCS.getInstruction()->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + + if (!StatepointCS.isInvoke()) { + return res; + } + + // We need to scan thorough exceptional relocations if it is invoke statepoint + LandingPadInst *LandingPad = + cast(StatepointCS.getInstruction())->getLandingPadInst(); + + // Search for extract value from landingpad instruction to which + // gc relocates will be attached + for (const User *LandingPadUser : LandingPad->users()) { + if (!isa(LandingPadUser)) { + continue; + } + + // gc relocates should be attached to this extract value + for (const User *U : LandingPadUser->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + } + return res; +} + +} +#endif diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 0000000..e241121 --- /dev/null +++ b/include/llvm/IR/TrackingMDRef.h @@ -0,0 +1,170 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class Metadata; +class MDNode; +class ValueAsMetadata; + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef TrackingMDNodeRef; +typedef TypedTrackingMDRef TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index a36fb0f..c2073c7 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -313,6 +313,9 @@ public: typedef Type * const *subtype_iterator; subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } typedef std::reverse_iterator subtype_reverse_iterator; subtype_reverse_iterator subtype_rbegin() const { diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index cea66a4..73a63ad 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -31,6 +31,7 @@ class TypeFinder { // To avoid walking constant expressions multiple times and other IR // objects, we keep several helper maps. DenseSet VisitedConstants; + DenseSet VisitedMetadata; DenseSet VisitedTypes; std::vector StructTypes; diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 033cd3e..160d71b 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -77,7 +77,7 @@ public: typedef PointerIntPair UserRef; private: - Use(const Use &U) LLVM_DELETED_FUNCTION; + Use(const Use &U) = delete; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 5df459b..7d8205d 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -45,8 +45,8 @@ struct UseListOrder { } private: - UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; - UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder(const UseListOrder &X) = delete; + UseListOrder &operator=(const UseListOrder &X) = delete; }; typedef std::vector UseListOrderStack; diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index f578227..d39378d 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -33,8 +33,8 @@ template struct OperandTraits; class User : public Value { - User(const User &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + User(const User &) = delete; + void *operator new(size_t) = delete; template friend struct HungoffOperandTraits; virtual void anchor(); diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 67665be..b7213a6 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; -class MDNode; class Module; class StringRef; class Twine; @@ -70,9 +69,9 @@ class Value { Type *VTy; Use *UseList; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueHandleBase; - ValueName *Name; + PointerIntPair NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? @@ -107,17 +106,12 @@ protected: private: template // UseT == 'Use' or 'const Use' class use_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { UseT *U; explicit use_iterator_impl(UseT *u) : U(u) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - use_iterator_impl() : U() {} bool operator==(const use_iterator_impl &x) const { return U == x.U; } @@ -148,17 +142,12 @@ private: template // UserTy == 'User' or 'const User' class user_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { use_iterator_impl UI; explicit user_iterator_impl(Use *U) : UI(U) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - user_iterator_impl() {} bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } @@ -189,15 +178,10 @@ private: } Use &getUse() const { return *UI; } - - /// \brief Return the operand # of this use in its User. - /// - /// FIXME: Replace all callers with a direct call to Use::getOperandNo. - unsigned getOperandNo() const { return UI->getOperandNo(); } }; - void operator=(const Value &) LLVM_DELETED_FUNCTION; - Value(const Value &) LLVM_DELETED_FUNCTION; + void operator=(const Value &) = delete; + Value(const Value &) = delete; protected: Value(Type *Ty, unsigned scid); @@ -226,10 +210,14 @@ public: LLVMContext &getContext() const; // \brief All values can potentially be named. - bool hasName() const { return Name != nullptr; } - ValueName *getValueName() const { return Name; } - void setValueName(ValueName *VN) { Name = VN; } + bool hasName() const { return getValueName() != nullptr; } + ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } + void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } + +private: + void destroyValueName(); +public: /// \brief Return a constant reference to the value's name. /// /// This is cheap and guaranteed to return the same reference as long as the @@ -258,6 +246,13 @@ public: /// guaranteed to be empty. void replaceAllUsesWith(Value *V); + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -276,6 +271,8 @@ public: return iterator_range(use_begin(), use_end()); } + bool user_empty() const { return UseList == nullptr; } + typedef user_iterator_impl user_iterator; typedef user_iterator_impl const_user_iterator; user_iterator user_begin() { return user_iterator(UseList); } @@ -345,9 +342,7 @@ public: ConstantStructVal, // This is an instance of ConstantStruct ConstantVectorVal, // This is an instance of ConstantVector ConstantPointerNullVal, // This is an instance of ConstantPointerNull - GenericMDNodeVal, // This is an instance of GenericMDNode - MDNodeFwdDeclVal, // This is an instance of MDNodeFwdDecl - MDStringVal, // This is an instance of MDString + MetadataAsValueVal, // This is an instance of MetadataAsValue InlineAsmVal, // This is an instance of InlineAsm InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; @@ -397,6 +392,9 @@ public: /// \brief Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer @@ -471,7 +469,8 @@ public: /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. - static const unsigned MaximumAlignment = 1u << 29; + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; /// \brief Mutate the type of this Value to be of the specified type. /// @@ -680,13 +679,6 @@ template <> struct isa_impl { } }; -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GenericMDNodeVal || - Val.getValueID() == Value::MDNodeFwdDeclVal; - } -}; - // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 460210e..355748e 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -56,55 +56,48 @@ private: PointerIntPair PrevPair; ValueHandleBase *Next; - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair VP; + Value* V; - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; + ValueHandleBase(const ValueHandleBase&) = delete; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(V) { + if (isValid(V)) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) { + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (isValid(VP.getPointer())) + if (isValid(V)) RemoveFromUseList(); } Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); + if (V == RHS) return RHS; + if (isValid(V)) RemoveFromUseList(); + V = RHS; + if (isValid(V)) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); + if (V == RHS.V) return RHS.V; + if (isValid(V)) RemoveFromUseList(); + V = RHS.V; + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); + return V; } - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } + Value *operator->() const { return V; } + Value &operator*() const { return *V; } protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } + Value *getValPtr() const { return V; } static bool isValid(Value *V) { return V && @@ -123,7 +116,7 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. /// /// List is the address of either the head of the list or a Next node within /// the existing use list. @@ -132,7 +125,7 @@ private: /// \brief Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. void AddToUseList(); /// \brief Remove this ValueHandle from its current use list. void RemoveFromUseList(); @@ -197,23 +190,20 @@ class AssertingVH friend struct DenseMapInfo >; #ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } + Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } + void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } #else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } + Value *ThePtr; + Value *getRawValPtr() const { return ThePtr; } + void setRawValPtr(Value *P) { ThePtr = P; } #endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. + // Convert a ValueTy*, which may be const, to the raw Value*. static Value *GetAsValue(Value *V) { return V; } static Value *GetAsValue(const Value *V) { return const_cast(V); } + ValueTy *getValPtr() const { return static_cast(getRawValPtr()); } + void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} @@ -221,7 +211,7 @@ public: AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} + AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} #endif operator ValueTy*() const { @@ -244,27 +234,23 @@ public: // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template struct DenseMapInfo > { - typedef DenseMapInfo PointerInfo; static inline AssertingVH getEmptyKey() { - return AssertingVH(PointerInfo::getEmptyKey()); + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getEmptyKey()); + return Res; } - static inline T* getTombstoneKey() { - return AssertingVH(PointerInfo::getTombstoneKey()); + static inline AssertingVH getTombstoneKey() { + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); + return Res; } static unsigned getHashValue(const AssertingVH &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val.getRawValPtr()); } -#ifndef NDEBUG static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - // Avoid downcasting AssertingVH to T*, as empty/tombstone keys may not - // be properly aligned pointers to T*. - return LHS.ValueHandleBase::getValPtr() == RHS.ValueHandleBase::getValPtr(); + return DenseMapInfo::isEqual(LHS.getRawValPtr(), + RHS.getRawValPtr()); } -#else - static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - return LHS == RHS; - } -#endif }; template diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index aa8a29d..08d6d17 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -27,11 +27,13 @@ #define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/UniqueLock.h" #include "llvm/Support/type_traits.h" #include +#include namespace llvm { @@ -79,11 +81,13 @@ class ValueMap { friend class ValueMapCallbackVH; typedef ValueMapCallbackVH ValueMapCVH; typedef DenseMap > MapT; + typedef DenseMap MDMapT; typedef typename Config::ExtraData ExtraData; MapT Map; + std::unique_ptr MDMap; ExtraData Data; - ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; - ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap(const ValueMap&) = delete; + ValueMap& operator=(const ValueMap&) = delete; public: typedef KeyT key_type; typedef ValueT mapped_type; @@ -91,12 +95,19 @@ public: typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} + : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} + : Map(NumInitBuckets), Data(Data) {} ~ValueMap() {} + bool hasMD() const { return MDMap; } + MDMapT &MD() { + if (!MDMap) + MDMap.reset(new MDMapT); + return *MDMap; + } + typedef ValueMapIterator iterator; typedef ValueMapConstIterator const_iterator; inline iterator begin() { return iterator(Map.begin()); } @@ -110,7 +121,10 @@ public: /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } - void clear() { Map.clear(); } + void clear() { + Map.clear(); + MDMap.reset(); + } /// Return 1 if the specified key is in the map, 0 otherwise. size_type count(const KeyT &Val) const { @@ -210,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH { : CallbackVH(const_cast(static_cast(Key))), Map(Map) {} + // Private constructor used to create empty/tombstone DenseMap keys. + ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} + public: KeyT Unwrap() const { return cast_or_null(getValPtr()); } @@ -252,19 +269,18 @@ public: template struct DenseMapInfo > { typedef ValueMapCallbackVH VH; - typedef DenseMapInfo PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), nullptr); + return VH(DenseMapInfo::getEmptyKey()); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), nullptr); + return VH(DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); + return DenseMapInfo::getHashValue(Val.Unwrap()); } static unsigned getHashValue(const KeyT &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val); } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 0272e20..43bd123 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -77,8 +77,8 @@ class VerifierPass { public: explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - PreservedAnalyses run(Module *M); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Module &M); + PreservedAnalyses run(Function &F); static StringRef name() { return "VerifierPass"; } }; diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index a4bc598..bcf8cf2 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -40,7 +40,7 @@ void initializeObjCARCOpts(PassRegistry&); void initializeVectorization(PassRegistry&); /// initializeInstCombine - Initialize all passes linked into the -/// ScalarOpts library. +/// InstCombine library. void initializeInstCombine(PassRegistry&); /// initializeIPO - Initialize all passes linked into the IPO library. @@ -65,6 +65,7 @@ void initializeTarget(PassRegistry&); void initializeAAEvalPass(PassRegistry&); void initializeAddDiscriminatorsPass(PassRegistry&); void initializeADCEPass(PassRegistry&); +void initializeBDCEPass(PassRegistry&); void initializeAliasAnalysisAnalysisGroup(PassRegistry&); void initializeAliasAnalysisCounterPass(PassRegistry&); void initializeAliasDebuggerPass(PassRegistry&); @@ -77,7 +78,6 @@ void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); -void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); @@ -106,7 +106,6 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); -void initializeDebugIRPass(PassRegistry&); void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); @@ -122,6 +121,7 @@ void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); +void initializeInstrProfilingPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); @@ -129,9 +129,8 @@ void initializeThreadSanitizerPass(PassRegistry&); void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); -void initializeEarlyCSEPass(PassRegistry&); +void initializeEarlyCSELegacyPassPass(PassRegistry &); void initializeExpandISelPseudosPass(PassRegistry&); -void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); @@ -143,9 +142,10 @@ void initializeIPCPPass(PassRegistry&); void initializeIPSCCPPass(PassRegistry&); void initializeIVUsersPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); +void initializeInductiveRangeCheckEliminationPass(PassRegistry&); void initializeIndVarSimplifyPass(PassRegistry&); void initializeInlineCostAnalysisPass(PassRegistry&); -void initializeInstCombinerPass(PassRegistry&); +void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); @@ -167,7 +167,7 @@ void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); -void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInfoWrapperPassPass(PassRegistry&); void initializeLoopInstSimplifyPass(PassRegistry&); void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); @@ -178,6 +178,7 @@ void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerBitSetsPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); @@ -200,6 +201,7 @@ void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); @@ -238,6 +240,7 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); +void initializeRewriteStatepointsForGCPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROAPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); @@ -245,6 +248,7 @@ void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); +void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); @@ -254,6 +258,7 @@ void initializeSpillPlacementPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); +void initializeStraightLineStrengthReducePass(PassRegistry &); void initializeStripDeadDebugInfoPass(PassRegistry&); void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); @@ -263,11 +268,9 @@ void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeDataLayoutPassPass(PassRegistry &); -void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); -void initializeFunctionTargetTransformInfoPass(PassRegistry &); -void initializeNoTTIPass(PassRegistry&); -void initializeTargetLibraryInfoPass(PassRegistry&); -void initializeAssumptionTrackerPass(PassRegistry &); +void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); +void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); +void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); void initializeScopedNoAliasAAPass(PassRegistry&); @@ -280,6 +283,7 @@ void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); +void initializeLoopAccessAnalysisPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); @@ -288,6 +292,10 @@ void initializeStackMapLivenessPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); void initializeRewriteSymbolsPass(PassRegistry&); +void initializeWinEHPreparePass(PassRegistry&); +void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); +void initializePlaceSafepointsPass(PassRegistry&); +void initializeDwarfEHPreparePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 0c9ce4a..56d27ca 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -67,6 +67,9 @@ struct LTOCodeGenerator { // Merge given module, return true on success. bool addModule(struct LTOModule *); + // Set the destination module. + void setModule(struct LTOModule *); + void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); void setCodePICModel(lto_codegen_model); @@ -117,6 +120,18 @@ struct LTOCodeGenerator { bool disableVectorization, std::string &errMsg); + // Optimizes the merged module. Returns true on success. + bool optimize(bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); + + // Compiles the merged optimized module into a single object file. It brings + // the object to a buffer, and returns the buffer to the caller. Return NULL + // if the compilation was not successful. + const void *compileOptimized(size_t *length, std::string &errMsg); + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); LLVMContext &getContext() { return Context; } @@ -124,9 +139,8 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); - bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, bool disableVectorization, - std::string &errMsg); + bool compileOptimized(raw_ostream &out, std::string &errMsg); + bool compileOptimizedToFile(const char **name, std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(GlobalValue &GV, ArrayRef Libcalls, std::vector &MustPreserveList, @@ -141,6 +155,7 @@ private: typedef StringMap StringSet; void initialize(); + void destroyMergedModule(); std::unique_ptr OwnedContext; LLVMContext &Context; Linker IRLinker; @@ -158,6 +173,7 @@ private: TargetOptions Options; lto_diagnostic_handler_t DiagHandler; void *DiagContext; + LTOModule *OwnedModule; }; } #endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 66e4e9c..18343e2 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -18,7 +18,6 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" -#include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" @@ -33,8 +32,8 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" #include @@ -50,6 +49,7 @@ namespace { (void) llvm::createAAEvalPass(); (void) llvm::createAggressiveDCEPass(); + (void) llvm::createBitTrackingDCEPass(); (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); @@ -79,6 +79,7 @@ namespace { (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); (void) llvm::createGCOVProfilerPass(); + (void) llvm::createInstrProfilingPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -86,6 +87,7 @@ namespace { (void) llvm::createGlobalsModRefPass(); (void) llvm::createIPConstantPropagationPass(); (void) llvm::createIPSCCPPass(); + (void) llvm::createInductiveRangeCheckEliminationPass(); (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); @@ -166,9 +168,10 @@ namespace { (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createRewriteSymbolsPass(); + (void) llvm::createStraightLineStrengthReducePass(); + (void) llvm::createMemDerefPrinter(); (void)new llvm::IntervalPartition(); - (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); ((llvm::Function*)nullptr)->viewCFGOnly(); llvm::RGPassManager RGM; diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index c957cc2..aac9dcd 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -10,45 +10,81 @@ #ifndef LLVM_LINKER_LINKER_H #define LLVM_LINKER_LINKER_H -#include "llvm/ADT/SmallPtrSet.h" - -#include +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/DiagnosticInfo.h" namespace llvm { -class DiagnosticInfo; class Module; class StructType; +class Type; /// This class provides the core functionality of linking in LLVM. It keeps a /// pointer to the merged module so far. It doesn't take ownership of the /// module since it is assumed that the user of this class will want to do /// something with it after the linking. class Linker { - public: - typedef std::function - DiagnosticHandlerFunction; +public: + struct StructTypeKeyInfo { + struct KeyTy { + ArrayRef ETypes; + bool IsPacked; + KeyTy(ArrayRef E, bool P); + KeyTy(const StructType *ST); + bool operator==(const KeyTy &that) const; + bool operator!=(const KeyTy &that) const; + }; + static StructType *getEmptyKey(); + static StructType *getTombstoneKey(); + static unsigned getHashValue(const KeyTy &Key); + static unsigned getHashValue(const StructType *ST); + static bool isEqual(const KeyTy &LHS, const StructType *RHS); + static bool isEqual(const StructType *LHS, const StructType *RHS); + }; + + typedef DenseSet NonOpaqueStructTypeSet; + typedef DenseSet OpaqueStructTypeSet; + + struct IdentifiedStructTypeSet { + // The set of opaque types is the composite module. + OpaqueStructTypeSet OpaqueStructTypes; + + // The set of identified but non opaque structures in the composite module. + NonOpaqueStructTypeSet NonOpaqueStructTypes; + + void addNonOpaque(StructType *Ty); + void addOpaque(StructType *Ty); + StructType *findNonOpaque(ArrayRef ETypes, bool IsPacked); + bool hasType(StructType *Ty); + }; + + Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Linker(Module *M); + ~Linker(); + + Module *getModule() const { return Composite; } + void deleteModule(); + + /// \brief Link \p Src into the composite. The source is destroyed. + /// Returns true on error. + bool linkInModule(Module *Src); - Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); - Linker(Module *M); - ~Linker(); + /// \brief Set the composite to the passed-in module. + void setModule(Module *Dst); - Module *getModule() const { return Composite; } - void deleteModule(); + static bool LinkModules(Module *Dest, Module *Src, + DiagnosticHandlerFunction DiagnosticHandler); - /// \brief Link \p Src into the composite. The source is destroyed. - /// Returns true on error. - bool linkInModule(Module *Src); + static bool LinkModules(Module *Dest, Module *Src); - static bool LinkModules(Module *Dest, Module *Src, - DiagnosticHandlerFunction DiagnosticHandler); +private: + void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Module *Composite; - static bool LinkModules(Module *Dest, Module *Src); + IdentifiedStructTypeSet IdentifiedStructTypes; - private: - void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); - Module *Composite; - SmallPtrSet IdentifiedStructTypes; - DiagnosticHandlerFunction DiagnosticHandler; + DiagnosticHandlerFunction DiagnosticHandler; }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 15a956b..56da95d 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -32,8 +32,8 @@ class raw_ostream; /// MCAsmBackend - Generic interface to target specific assembler backends. class MCAsmBackend { - MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + MCAsmBackend(const MCAsmBackend &) = delete; + void operator=(const MCAsmBackend &) = delete; protected: // Can only create subclasses. MCAsmBackend(); @@ -61,20 +61,6 @@ public: /// markers. If not, data region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// isSectionAtomizable - Check whether the given section can be split into - /// atoms. - /// - /// \see MCAssembler::isSymbolLinkerVisible(). - virtual bool isSectionAtomizable(const MCSection &Section) const { - return true; - } - /// @name Target Fixup Interfaces /// @{ diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 4f38aac..ee245e9 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -42,11 +42,11 @@ enum class EncodingType { } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling }; namespace LCOMM { @@ -123,6 +123,10 @@ protected: /// file. Defaults to "L" const char *PrivateGlobalPrefix; + /// This prefix is used for labels for basic blocks. Defaults to the same as + /// PrivateGlobalPrefix. + const char *PrivateLabelPrefix; + /// This prefix is used for symbols that should be passed through the /// assembler but be removed by the linker. This is 'l' on Darwin, currently /// used for some ObjC metadata. The default of "" meast that for this system @@ -215,7 +219,8 @@ protected: //===--- Global Variable Emission Directives --------------------------===// - /// This is the directive used to declare a global entity. Defaults to NULL. + /// This is the directive used to declare a global entity. Defaults to + /// ".globl". const char *GlobalDirective; /// True if the expression @@ -264,6 +269,9 @@ protected: /// to false. bool HasNoDeadStrip; + /// Used to declare a global as being a weak symbol. Defaults to ".weak". + const char *WeakDirective; + /// This directive, if non-null, is used to declare a global as being a weak /// undefined symbol. Defaults to NULL. const char *WeakRefDirective; @@ -373,6 +381,12 @@ public: return nullptr; } + /// \brief True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; @@ -414,6 +428,7 @@ public: bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { return LinkerPrivateGlobalPrefix[0] != '\0'; } @@ -452,6 +467,7 @@ public: bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakDirective() const { return WeakDirective; } const char *getWeakRefDirective() const { return WeakRefDirective; } bool hasWeakDefDirective() const { return HasWeakDefDirective; } bool hasWeakDefCanBeHiddenDirective() const { @@ -473,13 +489,16 @@ public: ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - /// Return true if the exception handling type uses the language-specific data - /// area (LSDA) format specified by the Itanium C++ ABI. - bool usesItaniumLSDAForExceptions() const { + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || ExceptionsType == ExceptionHandling::ARM || - // This Windows EH type uses the Itanium LSDA encoding. - ExceptionsType == ExceptionHandling::ItaniumWinEH); + ExceptionsType == ExceptionHandling::WinEH); + } + + bool usesWindowsCFI() const { + return ExceptionsType == ExceptionHandling::WinEH; } bool doesDwarfUseRelocationsAcrossSections() const { diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index 3d249f9..d587c3c 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -19,9 +19,9 @@ namespace llvm { class MCAsmInfoDarwin : public MCAsmInfo { - virtual void anchor(); public: explicit MCAsmInfoDarwin(); + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; }; } diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 681a317..8c56f88 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -46,8 +47,8 @@ class MCAsmBackend; class MCFragment : public ilist_node { friend class MCAsmLayout; - MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; - void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; + MCFragment(const MCFragment&) = delete; + void operator=(const MCFragment&) = delete; public: enum FragmentType { @@ -562,8 +563,8 @@ public: class MCSectionData : public ilist_node { friend class MCAsmLayout; - MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; - void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; + MCSectionData(const MCSectionData&) = delete; + void operator=(const MCSectionData&) = delete; public: typedef iplist FragmentListType; @@ -864,8 +865,8 @@ public: unsigned Update; } VersionMinInfoType; private: - MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; - void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; + MCAssembler(const MCAssembler&) = delete; + void operator=(const MCAssembler&) = delete; MCContext &Context; @@ -881,6 +882,8 @@ private: iplist Symbols; + DenseSet LocalsUsedInReloc; + /// The map of sections to their associated assembler backend data. // // FIXME: Avoid this indirection? @@ -980,6 +983,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index d3b5617..ddf0f82 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -22,8 +22,8 @@ template class SmallVectorImpl; /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: - MCCodeEmitter(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; + MCCodeEmitter(const MCCodeEmitter &) = delete; + void operator=(const MCCodeEmitter &) = delete; protected: // Can only create subclasses. MCCodeEmitter(); diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index f209448..cd96dfd 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -47,8 +47,8 @@ namespace llvm { /// of the sections that it creates. /// class MCContext { - MCContext(const MCContext&) LLVM_DELETED_FUNCTION; - MCContext &operator=(const MCContext&) LLVM_DELETED_FUNCTION; + MCContext(const MCContext&) = delete; + MCContext &operator=(const MCContext&) = delete; public: typedef StringMap SymbolTable; private: @@ -237,6 +237,8 @@ namespace llvm { MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// LookupSymbol - Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(StringRef Name) const; MCSymbol *LookupSymbol(const Twine &Name) const; @@ -269,11 +271,15 @@ namespace llvm { } const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); + unsigned Flags); + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group); const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind, - unsigned EntrySize, StringRef Group); + unsigned Flags, unsigned EntrySize, + StringRef Group, bool Unique); void renameELFSection(const MCSectionELF *Section, StringRef Name); diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index a221d26..c266acf 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,16 +16,16 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" #include -#include #include #include +#include namespace llvm { class MCAsmBackend; diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 421e7a0..9763635 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -41,6 +41,7 @@ protected: public: static uint8_t getOSABI(Triple::OSType OSType) { switch (OSType) { + case Triple::PS4: case Triple::FreeBSD: return ELF::ELFOSABI_FREEBSD; case Triple::Linux: diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index f0e8611..5e2ef3f 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -44,8 +44,8 @@ public: private: ExprKind Kind; - MCExpr(const MCExpr&) LLVM_DELETED_FUNCTION; - void operator=(const MCExpr&) LLVM_DELETED_FUNCTION; + MCExpr(const MCExpr&) = delete; + void operator=(const MCExpr&) = delete; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, @@ -194,6 +194,7 @@ public: VK_ARM_TARGET1, VK_ARM_TARGET2, VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) VK_ARM_TLSLDO, // symbol(tlsldo) VK_ARM_TLSCALL, // symbol(tlscall) VK_ARM_TLSDESC, // symbol(tlsdesc) diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 6918280..aed7347 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -31,7 +31,7 @@ class MCInst; /// MCOperand - Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { - enum MachineOperandType { + enum MachineOperandType : unsigned char { kInvalid, ///< Uninitialized. kRegister, ///< Register operand. kImmediate, ///< Immediate operand. @@ -39,7 +39,7 @@ class MCOperand { kExpr, ///< Relocatable immediate operand. kInst ///< Sub-instruction operand. }; - unsigned char Kind; + MachineOperandType Kind; union { unsigned RegVal; @@ -139,7 +139,7 @@ public: return Op; } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; }; @@ -169,33 +169,35 @@ public: } void clear() { Operands.clear(); } - size_t size() { return Operands.size(); } + size_t size() const { return Operands.size(); } typedef SmallVectorImpl::iterator iterator; + typedef SmallVectorImpl::const_iterator const_iterator; iterator begin() { return Operands.begin(); } - iterator end() { return Operands.end(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { return Operands.insert(I, Op); } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; /// \brief Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. - void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr, - const MCInstPrinter *Printer = nullptr, + void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, StringRef Separator = " ") const; }; inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { - MO.print(OS, nullptr); + MO.print(OS); return OS; } inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { - MI.print(OS, nullptr); + MI.print(OS); return OS; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 95124c3..dce3a06 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -95,12 +95,14 @@ public: void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } /// Utility function to print immediates in decimal or hex. - format_object1 formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + format_object formatImm(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; + format_object formatDec(int64_t Value) const; + format_object formatHex(int64_t Value) const; + format_object formatHex(uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index d4f93c1..3609893 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -44,11 +44,12 @@ namespace MCOI { /// Operand Type - Operands are tagged with one of the values of this enum. enum OperandType { - OPERAND_UNKNOWN, - OPERAND_IMMEDIATE, - OPERAND_REGISTER, - OPERAND_MEMORY, - OPERAND_PCREL + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 }; } diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index f531de8..a386deb 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -32,8 +32,8 @@ namespace llvm { MCLabel(unsigned instance) : Instance(instance) {} - MCLabel(const MCLabel&) LLVM_DELETED_FUNCTION; - void operator=(const MCLabel&) LLVM_DELETED_FUNCTION; + MCLabel(const MCLabel&) = delete; + void operator=(const MCLabel&) = delete; public: /// getInstance - Get the current instance of this Directional Local Label. unsigned getInstance() const { return Instance; } diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 1f91b0d..890d638 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -18,8 +18,8 @@ #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 0c5aa8a..e4681c0 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -68,12 +68,10 @@ public: /// @name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -97,8 +95,14 @@ class MachObjectWriter : public MCObjectWriter { /// @name Relocation Data /// @{ - llvm::DenseMap > Relocations; + struct RelAndSymbol { + const MCSymbolData *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap> Relocations; llvm::DenseMap IndirectSymBase; /// @} @@ -213,9 +217,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[SD].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -231,7 +241,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c..430075c 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -37,8 +37,8 @@ class MCValue; /// The object writer also contains a number of helper methods for writing /// binary data to the output stream. class MCObjectWriter { - MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION; - void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION; + MCObjectWriter(const MCObjectWriter &) = delete; + void operator=(const MCObjectWriter &) = delete; protected: raw_ostream &OS; @@ -76,12 +76,10 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index a9a30f1..2f681d6 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -31,8 +31,8 @@ class AsmLexer : public MCAsmLexer { StringRef CurBuf; bool isAtStartOfLine; - void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; - AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION; + void operator=(const AsmLexer&) = delete; + AsmLexer(const AsmLexer&) = delete; protected: /// LexToken - Read the next token and return its code. diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index b05891c..14f8ade 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -124,8 +124,8 @@ class MCAsmLexer { SMLoc ErrLoc; std::string Err; - MCAsmLexer(const MCAsmLexer &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION; + MCAsmLexer(const MCAsmLexer &) = delete; + void operator=(const MCAsmLexer &) = delete; protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 34188e6..83ffbb5 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -68,8 +68,8 @@ public: ExtensionDirectiveHandler; private: - MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParser &) LLVM_DELETED_FUNCTION; + MCAsmParser(const MCAsmParser &) = delete; + void operator=(const MCAsmParser &) = delete; MCTargetAsmParser *TargetParser; diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index bfc0afa..53515d7 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -21,8 +21,8 @@ class Twine; /// which is implemented by target and object file assembly parser /// implementations. class MCAsmParserExtension { - MCAsmParserExtension(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; + MCAsmParserExtension(const MCAsmParserExtension &) = delete; + void operator=(const MCAsmParserExtension &) = delete; MCAsmParser *Parser; diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index df556e7..8e25ee1 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -114,6 +114,10 @@ struct MCRegisterDesc { // RegUnits - Points to the list of register units. The low 4 bits holds the // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; }; /// MCRegisterInfo base class - We assume that the target defines a static @@ -157,6 +161,8 @@ private: unsigned NumRegUnits; // Number of regunits. const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. const MCPhysReg *DiffLists; // Pointer to the difflists array + const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. const char *RegStrings; // Pointer to the string table. const char *RegClassStrings; // Pointer to the class strings. const uint16_t *SubRegIndices; // Pointer to the subreg lookup @@ -227,8 +233,10 @@ public: // These iterators are allowed to sub-class DiffListIterator and access // internal list pointers. friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; friend class MCSuperRegIterator; friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; /// \brief Initialize MCRegisterInfo, called by TableGen @@ -239,6 +247,7 @@ public: const MCPhysReg (*RURoots)[2], unsigned NRU, const MCPhysReg *DL, + const unsigned *RUMS, const char *Strings, const char *ClassStrings, const uint16_t *SubIndices, @@ -251,6 +260,7 @@ public: PCReg = PC; Classes = C; DiffLists = DL; + RegUnitMaskSequences = RUMS; RegStrings = Strings; RegClassStrings = ClassStrings; NumClasses = NC; @@ -452,6 +462,38 @@ public: } }; +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + unsigned getSubReg() const { + return *SRIter; + } + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + /// MCSuperRegIterator enumerates all super-registers of Reg. /// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { @@ -513,6 +555,36 @@ public: } }; +/// MCRegUnitIterator enumerates a list of register units and their associated +/// lane masks for Reg. The register units are in ascending numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const unsigned *MaskListIter; +public: + MCRegUnitMaskIterator() {} + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + // Each register unit has one or two root registers. The complete set of // registers containing a register unit is the union of the roots and their // super-registers. All registers aliasing Unit can be visited like this: diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h index 9dab900..40e0217 100644 --- a/include/llvm/MC/MCRelocationInfo.h +++ b/include/llvm/MC/MCRelocationInfo.h @@ -28,8 +28,8 @@ 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; + MCRelocationInfo(const MCRelocationInfo &) = delete; + void operator=(const MCRelocationInfo &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index de2678a..8aec9c8 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -35,8 +35,8 @@ namespace llvm { }; private: - MCSection(const MCSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCSection&) LLVM_DELETED_FUNCTION; + MCSection(const MCSection&) = delete; + void operator=(const MCSection&) = delete; protected: MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} SectionVariant Variant; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5ec23f1..6d864b4 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -39,6 +39,8 @@ class MCSectionELF : public MCSection { /// below. unsigned Flags; + bool Unique; + /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a /// section does not contain fixed-sized entries 'EntrySize' will be 0. @@ -48,10 +50,10 @@ class MCSectionELF : public MCSection { private: friend class MCContext; - MCSectionELF(StringRef Section, unsigned type, unsigned flags, - SectionKind K, unsigned entrySize, const MCSymbol *group) - : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), - EntrySize(entrySize), Group(group) {} + MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, + unsigned entrySize, const MCSymbol *group, bool Unique) + : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), + Unique(Unique), EntrySize(entrySize), Group(group) {} ~MCSectionELF(); void setSectionName(StringRef Name) { SectionName = Name; } @@ -92,10 +94,6 @@ public: static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } - - // Return the entry size for sections with fixed-width data. - static unsigned DetermineEntrySize(SectionKind Kind); - }; } // end namespace llvm diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index df896a6..f0be77f 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -49,14 +49,14 @@ typedef std::pair MCSectionSubPair; /// /// If target foo wants to use this, it should implement 3 classes: /// * FooTargetStreamer : public MCTargetStreamer -/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetAsmStreamer : 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 +/// The FooTargetAsmStreamer 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. /// @@ -66,8 +66,9 @@ typedef std::pair MCSectionSubPair; /// 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. +/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should +/// *never* be treated differently. Callers should always talk to a +/// FooTargetStreamer. class MCTargetStreamer { protected: MCStreamer &Streamer; @@ -138,6 +139,7 @@ public: StringRef StringValue = ""); virtual void emitFPU(unsigned FPU); virtual void emitArch(unsigned Arch); + virtual void emitArchExtension(unsigned ArchExt); virtual void emitObjectArch(unsigned Arch); virtual void finishAttributeSection(); virtual void emitInst(uint32_t Inst, char Suffix = '\0'); @@ -174,8 +176,8 @@ class MCStreamer { MCContext &Context; std::unique_ptr TargetStreamer; - MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer(const MCStreamer &) = delete; + MCStreamer &operator=(const MCStreamer &) = delete; std::vector DwarfFrameInfos; MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 9d09bd8..3984a1f 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -28,6 +28,7 @@ class StringRef; /// class MCSubtargetInfo { std::string TargetTriple; // Target triple + std::string CPU; // CPU being targeted. ArrayRef ProcFeatures; // Processor feature list ArrayRef ProcDesc; // Processor descriptions @@ -59,6 +60,11 @@ public: return TargetTriple; } + /// getCPU - Return the CPU string. + StringRef getCPU() const { + return CPU; + } + /// getFeatureBits - Return the feature bits. /// uint64_t getFeatureBits() const { @@ -136,6 +142,15 @@ public: /// Initialize an InstrItineraryData instance. void initInstrItins(InstrItineraryData &InstrItins) const; + + /// Check whether the CPU string is valid. + bool isCPUStringValid(StringRef CPU) { + auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), + [=](const SubtargetFeatureKV &KV) { + return CPU == KV.Key; + }); + return Found != ProcDesc.end(); + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 0b3c3ce..53443b0 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -53,6 +53,9 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + /// IsUsed - True if this symbol has been used. mutable unsigned IsUsed : 1; @@ -61,10 +64,10 @@ namespace llvm { friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsUsed(false) {} + IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} - MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; + MCSymbol(const MCSymbol&) = delete; + void operator=(const MCSymbol&) = delete; public: /// getName - Get the symbol name. StringRef getName() const { return Name; } @@ -79,6 +82,19 @@ namespace llvm { bool isUsed() const { return IsUsed; } void setUsed(bool Value) const { IsUsed = Value; } + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; + Section = nullptr; + IsRedefinable = false; + } + } + /// @} /// @name Associated Sections /// @{ diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index cbbb591..20e7b81 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -38,8 +38,8 @@ class raw_ostream; /// 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; + MCSymbolizer(const MCSymbolizer &) = delete; + void operator=(const MCSymbolizer &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index cf92307..8412b1d 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -13,7 +13,6 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" - #include namespace llvm { @@ -92,8 +91,8 @@ public: }; private: - MCTargetAsmParser(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; + MCTargetAsmParser(const MCTargetAsmParser &) = delete; + void operator=(const MCTargetAsmParser &) = delete; protected: // Can only create subclasses. MCTargetAsmParser(); diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index de79bae..ce28a19 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -10,8 +10,12 @@ #ifndef LLVM_MC_MCTARGETOPTIONS_H #define LLVM_MC_MCTARGETOPTIONS_H +#include + namespace llvm { +class StringRef; + class MCTargetOptions { public: enum AsmInstrumentation { @@ -31,6 +35,11 @@ public: bool ShowMCInst : 1; bool AsmVerbose : 1; int DwarfVersion; + /// getABIName - If this returns a non-empty string this represents the + /// textual name of the ABI that we want the backend to use, e.g. o32, or + /// aapcs-linux. + StringRef getABIName() const; + std::string ABIName; MCTargetOptions(); }; @@ -45,7 +54,8 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && - ARE_EQUAL(DwarfVersion)); + ARE_EQUAL(DwarfVersion) && + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 6d4eb0e..af23a92 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -15,8 +15,8 @@ #ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H #define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H -#include "llvm/Support/CommandLine.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; cl::opt AsmInstrumentation( @@ -40,6 +40,11 @@ cl::opt ShowMCInst("asm-show-inst", cl::desc("Emit internal instruction representation to " "assembly file")); +cl::opt +ABIName("target-abi", cl::Hidden, + cl::desc("The name of the ABI to be targeted from the backend."), + cl::init("")); + static inline MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; Options.SanitizeAddress = @@ -47,6 +52,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { Options.MCRelaxAll = RelaxAll; Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; + Options.ABIName = ABIName; return Options; } diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index dd86979..175fed0 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -55,7 +55,7 @@ public: bool isAbsolute() const { return !SymA && !SymB; } /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; /// dump - Print the value to stderr. void dump() const; diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index dad7bb5..956e436 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,10 +11,11 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { - class MCFixup; - class MCObjectWriter; - class MCValue; - class raw_ostream; +class MCAsmBackend; +class MCFixup; +class MCObjectWriter; +class MCValue; +class raw_ostream; class MCWinCOFFObjectTargetWriter { virtual void anchor(); @@ -27,9 +28,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsCrossSection) const = 0; + virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection, + const MCAsmBackend &MAB) const = 0; virtual bool recordRelocation(const MCFixup &) const { return true; } }; diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 85a91c6..9e8b68f 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -55,7 +55,6 @@ class SectionKind { /// MergeableConst - These are sections for merging fixed-length /// constants together. For example, this can be used to unique /// constant pool entries etc. - MergeableConst, /// MergeableConst4 - This is a section used by 4-byte constants, /// for example, floats. @@ -151,8 +150,8 @@ public: bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } bool isMergeableConst() const { - return K == MergeableConst || K == MergeableConst4 || - K == MergeableConst8 || K == MergeableConst16; + return K == MergeableConst4 || K == MergeableConst8 || + K == MergeableConst16; } bool isMergeableConst4() const { return K == MergeableConst4; } bool isMergeableConst8() const { return K == MergeableConst8; } @@ -216,7 +215,6 @@ public: static SectionKind getMergeable4ByteCString() { return get(Mergeable4ByteCString); } - static SectionKind getMergeableConst() { return get(MergeableConst); } static SectionKind getMergeableConst4() { return get(MergeableConst4); } static SectionKind getMergeableConst8() { return get(MergeableConst8); } static SectionKind getMergeableConst16() { return get(MergeableConst16); } diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 7c03dcd..4f8e281 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,8 +14,8 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -41,6 +41,9 @@ struct ArchiveMemberHeader { sys::fs::perms getAccessMode() const; sys::TimeValue getLastModified() const; + llvm::StringRef getRawLastModified() const { + return StringRef(LastModified, sizeof(LastModified)).rtrim(" "); + } unsigned getUID() const; unsigned getGID() const; }; @@ -78,17 +81,23 @@ public: sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); } + StringRef getRawLastModified() const { + return getHeader()->getRawLastModified(); + } 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; } + uint64_t getSize() const; + /// \return the size in the archive header for this member. + uint64_t getRawSize() const; StringRef getBuffer() const { return StringRef(Data.data() + StartOfFile, getSize()); } + uint64_t getChildOffset() const; ErrorOr getMemoryBufferRef() const; @@ -169,13 +178,12 @@ public: enum Kind { K_GNU, + K_MIPS64, K_BSD, K_COFF }; - Kind kind() const { - return Format; - } + Kind kind() const { return (Kind)Format; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; @@ -196,12 +204,14 @@ public: child_iterator findSym(StringRef name) const; bool hasSymbolTable() const; + child_iterator getSymbolTableChild() const { return SymbolTable; } private: child_iterator SymbolTable; child_iterator StringTable; child_iterator FirstRegular; - Kind Format; + unsigned Format : 2; + unsigned IsThin : 1; }; } diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 4b2b7e6..a3d6d0d 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -28,8 +28,8 @@ namespace object { class Binary { private: - Binary() LLVM_DELETED_FUNCTION; - Binary(const Binary &other) LLVM_DELETED_FUNCTION; + Binary() = delete; + Binary(const Binary &other) = delete; unsigned int TypeID; diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 3368d68..522bf68 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -276,12 +276,14 @@ public: } const StringTableOffset &getStringTableOffset() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->Name.Offset : CS32->Name.Offset; } uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } int32_t getSectionNumber() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); if (CS16) { // Reserved sections are returned as negative numbers. if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) @@ -291,13 +293,18 @@ public: return static_cast(CS32->SectionNumber); } - uint16_t getType() const { return CS16 ? CS16->Type : CS32->Type; } + uint16_t getType() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Type : CS32->Type; + } uint8_t getStorageClass() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->StorageClass : CS32->StorageClass; } uint8_t getNumberOfAuxSymbols() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; } @@ -360,6 +367,8 @@ public: } private: + bool isSet() const { return CS16 || CS32; } + const coff_symbol16 *CS16; const coff_symbol32 *CS32; }; @@ -593,9 +602,6 @@ protected: bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 3fcd98d..e7eba97 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -48,6 +48,9 @@ public: virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const = 0; + virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; + virtual uint32_t getSectionType(SectionRef Sec) const = 0; + static inline bool classof(const Binary *v) { return v->isELF(); } }; @@ -97,10 +100,7 @@ protected: bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -177,6 +177,20 @@ protected: return DRI; } + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + // A symbol is exported if its binding is either GLOBAL or WEAK, and its + // visibility is either DEFAULT or PROTECTED. All other symbols are not + // exported. + if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && + (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)) + return true; + + return false; + } + // 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. @@ -201,6 +215,9 @@ public: std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const override; + uint64_t getSectionFlags(SectionRef Sec) const override; + uint32_t getSectionType(SectionRef Sec) const override; + uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; @@ -262,6 +279,18 @@ std::error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, } template +uint64_t ELFObjectFile::getSectionFlags(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_flags; +} + +template +uint32_t ELFObjectFile::getSectionType(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_type; +} + +template std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); @@ -280,12 +309,16 @@ std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, const Elf_Ehdr *Header = EF.getHeader(); Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) + // Clear the ARM/Thumb or microMIPS indicator flag. + if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + ESym->getType() == ELF::STT_FUNC) Result &= ~1; - if (Header->e_type == ELF::ET_REL) - Result += EF.getSection(ESym)->sh_addr; + if (Header->e_type == ELF::ET_REL) { + const typename ELFFile::Elf_Shdr * Section = EF.getSection(ESym); + if (Section != nullptr) + Result += Section->sh_addr; + } return object_error::success; } @@ -373,6 +406,9 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + return Result; } @@ -451,27 +487,11 @@ bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { } template -bool ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec) const { - return toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; -} - -template bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } template -bool ELFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { - return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; -} - -template -bool ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - return !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); -} - -template bool ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 4bc0c7c..9a97f7b 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -302,7 +302,10 @@ struct Elf_Rel_Base, false> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template @@ -321,9 +324,12 @@ struct Elf_Rel_Base, false> { 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; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -338,7 +344,10 @@ struct Elf_Rel_Base, true> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template @@ -358,9 +367,12 @@ struct Elf_Rel_Base, true> { 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; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -380,10 +392,14 @@ struct Elf_Rel_Impl, 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)); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(uint32_t t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); } }; @@ -401,10 +417,14 @@ struct Elf_Rel_Impl, 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); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); } }; diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 687611d..45cbdbd 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -40,7 +40,8 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) // 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) @@ -71,14 +72,20 @@ struct LocalGlobalWeakSymbols { std::vector Global; std::vector Weak; }; + +struct SectionOrType { + StringRef sectionNameOrType; +}; + struct Section { - enum class SectionKind { RawContent, Relocation }; + enum class SectionKind { Group, RawContent, Relocation }; SectionKind Kind; StringRef Name; ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; StringRef Link; + StringRef Info; llvm::yaml::Hex64 AddressAlign; Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); @@ -91,6 +98,17 @@ struct RawContentSection : Section { return S->Kind == SectionKind::RawContent; } }; + +struct Group : Section { + // Members of a group contain a flag and a list of section indices + // that are part of the group. + std::vector Members; + Group() : Section(SectionKind::Group) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::Group; + } +}; + struct Relocation { llvm::yaml::Hex64 Offset; int64_t Addend; @@ -98,7 +116,6 @@ struct Relocation { StringRef Symbol; }; struct RelocationSection : Section { - StringRef Info; std::vector Relocations; RelocationSection() : Section(SectionKind::Relocation) {} static bool classof(const Section *S) { @@ -121,6 +138,7 @@ struct Object { LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) namespace llvm { namespace yaml { @@ -186,6 +204,11 @@ struct ScalarEnumerationTraits { }; template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); +}; + +template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; @@ -215,6 +238,10 @@ struct MappingTraits { static void mapping(IO &IO, ELFYAML::Object &Object); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); +}; + } // end namespace yaml } // end namespace llvm diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index b650d5d..74f4666 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -36,7 +36,10 @@ public: std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue *getSymbolGV(DataRefImpl Symb) const; + GlobalValue *getSymbolGV(DataRefImpl Symb); + const GlobalValue *getSymbolGV(DataRefImpl Symb) const { + return const_cast(this)->getSymbolGV(Symb); + } basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; @@ -46,6 +49,7 @@ public: Module &getModule() { return *M; } + std::unique_ptr takeModule(); static inline bool classof(const Binary *v) { return v->isIR(); @@ -61,8 +65,8 @@ public: static ErrorOr findBitcodeInMemBuffer(MemoryBufferRef Object); - static ErrorOr> - createIRObjectFile(MemoryBufferRef Object, LLVMContext &Context); + static ErrorOr> create(MemoryBufferRef Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 768cda6..a552aca 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -200,6 +200,7 @@ public: // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + unsigned getSectionType(SectionRef Sec) const; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; @@ -223,10 +224,7 @@ public: bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -348,8 +346,8 @@ public: getSegmentLoadCommand(const LoadCommandInfo &L) const; MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_options_command - getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::linker_option_command + getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; MachO::dylib_command @@ -360,10 +358,30 @@ public: getDylinkerCommand(const LoadCommandInfo &L) const; MachO::uuid_command getUuidCommand(const LoadCommandInfo &L) const; + MachO::rpath_command + getRpathCommand(const LoadCommandInfo &L) const; MachO::source_version_command getSourceVersionCommand(const LoadCommandInfo &L) const; MachO::entry_point_command getEntryPointCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command + getEncryptionInfoCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command_64 + getEncryptionInfoCommand64(const LoadCommandInfo &L) const; + MachO::sub_framework_command + getSubFrameworkCommand(const LoadCommandInfo &L) const; + MachO::sub_umbrella_command + getSubUmbrellaCommand(const LoadCommandInfo &L) const; + MachO::sub_library_command + getSubLibraryCommand(const LoadCommandInfo &L) const; + MachO::sub_client_command + getSubClientCommand(const LoadCommandInfo &L) const; + MachO::routines_command + getRoutinesCommand(const LoadCommandInfo &L) const; + MachO::routines_command_64 + getRoutinesCommand64(const LoadCommandInfo &L) const; + MachO::thread_command + getThreadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -377,6 +395,7 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; ArrayRef getDyldInfoRebaseOpcodes() const; ArrayRef getDyldInfoBindOpcodes() const; ArrayRef getDyldInfoWeakBindOpcodes() const; @@ -419,6 +438,7 @@ private: const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *LinkOptHintsLoadCmd; const char *DyldInfoLoadCmd; const char *UuidLoadCmd; bool HasPageZeroSegment; diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 46cf3fb..93f6654 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -16,8 +16,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/Binary.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" @@ -51,6 +51,10 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + uint32_t getCPUSubType() const { return Header.cpusubtype; } + uint32_t getOffset() const { return Header.offset; } + uint32_t getSize() const { return Header.size; } + uint32_t getAlign() const { return Header.align; } std::string getArchTypeName() const { Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); return T.getArchName(); @@ -58,7 +62,7 @@ public: ErrorOr> getAsObjectFile() const; - std::error_code getAsArchive(std::unique_ptr &Result) const; + ErrorOr> getAsArchive() const; }; class object_iterator { diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 68b873a..b7e19b9 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -105,10 +105,7 @@ public: bool isText() const; bool isData() const; bool isBSS() const; - bool isRequiredForExecution() const; bool isVirtual() const; - bool isZeroInit() const; - bool isReadOnlyData() const; bool containsSymbol(SymbolRef S) const; @@ -121,6 +118,7 @@ public: section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; }; /// SymbolRef - This is a value type class that represents a single symbol in @@ -182,8 +180,8 @@ public: /// figures out which type to create. class ObjectFile : public SymbolicFile { virtual void anchor(); - ObjectFile() LLVM_DELETED_FUNCTION; - ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; + ObjectFile() = delete; + ObjectFile(const ObjectFile &other) = delete; protected: ObjectFile(unsigned int Type, MemoryBufferRef Source); @@ -233,11 +231,8 @@ protected: virtual bool isSectionText(DataRefImpl Sec) const = 0; virtual bool isSectionData(DataRefImpl Sec) const = 0; virtual bool isSectionBSS(DataRefImpl Sec) const = 0; - virtual bool isSectionRequiredForExecution(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; - virtual bool isSectionZeroInit(DataRefImpl Sec) const = 0; - virtual bool isSectionReadOnlyData(DataRefImpl Sec) const = 0; virtual bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; @@ -417,22 +412,10 @@ inline bool SectionRef::isBSS() const { return OwningObject->isSectionBSS(SectionPimpl); } -inline bool SectionRef::isRequiredForExecution() const { - return OwningObject->isSectionRequiredForExecution(SectionPimpl); -} - inline bool SectionRef::isVirtual() const { return OwningObject->isSectionVirtual(SectionPimpl); } -inline bool SectionRef::isZeroInit() const { - return OwningObject->isSectionZeroInit(SectionPimpl); -} - -inline bool SectionRef::isReadOnlyData() const { - return OwningObject->isSectionReadOnlyData(SectionPimpl); -} - inline bool SectionRef::containsSymbol(SymbolRef S) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.getRawDataRefImpl()); @@ -454,6 +437,10 @@ inline DataRefImpl SectionRef::getRawDataRefImpl() const { return SectionPimpl; } +inline const ObjectFile *SectionRef::getObject() const { + return OwningObject; +} + /// RelocationRef inline RelocationRef::RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner) diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 435799a..f7b7cb4 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -87,9 +87,10 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6, // Specific to the object file format + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format // (e.g. section symbols) - SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary }; BasicSymbolRef() : OwningObject(nullptr) { } diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index dcaa540..9459a3d 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -29,8 +29,8 @@ class ArgList; /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. class Arg { - Arg(const Arg &) LLVM_DELETED_FUNCTION; - void operator=(const Arg &) LLVM_DELETED_FUNCTION; + Arg(const Arg &) = delete; + void operator=(const Arg &) = delete; private: /// \brief The option this argument is an instance of. diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 3f8547e..f5ded94 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -91,8 +91,8 @@ public: /// and to iterate over groups of arguments. class ArgList { private: - ArgList(const ArgList &) LLVM_DELETED_FUNCTION; - void operator=(const ArgList &) LLVM_DELETED_FUNCTION; + ArgList(const ArgList &) = delete; + void operator=(const ArgList &) = delete; public: typedef SmallVector arglist_type; diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index b7caa6e..7206bf2 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -21,7 +21,7 @@ namespace opt { unsigned ID; private: - explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION; + explicit OptSpecifier(bool) = delete; public: OptSpecifier() : ID(0) {} diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index c2b9f95..6e92d96 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -83,8 +83,8 @@ class Pass { AnalysisResolver *Resolver; // Used to resolve analysis const void *PassID; PassKind Kind; - void operator=(const Pass&) LLVM_DELETED_FUNCTION; - Pass(const Pass &) LLVM_DELETED_FUNCTION; + void operator=(const Pass&) = delete; + Pass(const Pass &) = delete; public: explicit Pass(PassKind K, char &pid) diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 9164305..38adb2d 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -120,7 +120,7 @@ public: class PMDataManager; class AnalysisResolver { private: - AnalysisResolver() LLVM_DELETED_FUNCTION; + AnalysisResolver() = delete; public: explicit AnalysisResolver(PMDataManager &P) : PM(P) { } diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h index d53daf1..d107618 100644 --- a/include/llvm/PassInfo.h +++ b/include/llvm/PassInfo.h @@ -138,8 +138,8 @@ public: } private: - void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; - PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; + void operator=(const PassInfo &) = delete; + PassInfo(const PassInfo &) = delete; }; } diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h deleted file mode 100644 index 2a191b3..0000000 --- a/include/llvm/PassManager.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- llvm/PassManager.h - Container for Passes ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a legacy redirect header for the old PassManager. It is intended to -// be used by clients that have not been converted to be aware of the new pass -// management infrastructure being built for LLVM, which is every client -// initially. Eventually this header (and the legacy management layer) will go -// away, but we want to minimize changes to out-of-tree users of LLVM in the -// interim. -// -// Note that this header *must not* be included into the same file as the new -// pass management infrastructure is included. Things will break spectacularly. -// If you are starting that conversion, you should switch to explicitly -// including LegacyPassManager.h and using the legacy namespace. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PASSMANAGER_H -#define LLVM_PASSMANAGER_H - -#include "llvm/IR/LegacyPassManager.h" - -namespace llvm { - -// Pull these into the llvm namespace so that existing code that expects it -// there can find it. -using legacy::PassManagerBase; -using legacy::PassManager; -using legacy::FunctionPassManager; - -} - -#endif diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 38fc8ca..4d393b3 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/iterator.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/raw_ostream.h" #include @@ -27,7 +28,7 @@ namespace llvm { class IndexedInstrProfReader; namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; class CoverageMapping; struct CounterExpressions; @@ -62,8 +63,12 @@ public: unsigned getExpressionID() const { return ID; } - bool operator==(const Counter &Other) const { - return Kind == Other.Kind && ID == Other.ID; + friend bool operator==(const Counter &LHS, const Counter &RHS) { + return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; + } + + friend bool operator!=(const Counter &LHS, const Counter &RHS) { + return !(LHS == RHS); } friend bool operator<(const Counter &LHS, const Counter &RHS) { @@ -153,24 +158,40 @@ struct CounterMappingRegion { SkippedRegion }; - static const unsigned EncodingHasCodeBeforeBits = 1; - Counter Count; unsigned FileID, ExpandedFileID; unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; RegionKind Kind; - /// \brief A flag that is set to true when there is already code before - /// this region on the same line. - /// This is useful to accurately compute the execution counts for a line. - bool HasCodeBefore; - - CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd, bool HasCodeBefore = false, - RegionKind Kind = CodeRegion) - : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), - ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), - Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, + unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) + : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), + LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), + ColumnEnd(ColumnEnd), Kind(Kind) {} + + static CounterMappingRegion + makeRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, CodeRegion); + } + + static CounterMappingRegion + makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, + ColumnStart, LineEnd, ColumnEnd, + ExpansionRegion); + } + + static CounterMappingRegion + makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, SkippedRegion); + } + inline std::pair startLoc() const { return std::pair(LineStart, ColumnStart); @@ -216,8 +237,10 @@ public: ArrayRef CounterValues = ArrayRef()) : Expressions(Expressions), CounterValues(CounterValues) {} + void setCounts(ArrayRef Counts) { CounterValues = Counts; } + void dump(const Counter &C, llvm::raw_ostream &OS) const; - void dump(const Counter &C) const { dump(C, llvm::outs()); } + void dump(const Counter &C) const { dump(C, dbgs()); } /// \brief Return the number of times that a region of code associated with /// this counter was executed. @@ -235,10 +258,14 @@ struct FunctionRecord { /// \brief The number of times this function was executed. uint64_t ExecutionCount; - FunctionRecord(StringRef Name, ArrayRef Filenames, - uint64_t ExecutionCount) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()), - ExecutionCount(ExecutionCount) {} + FunctionRecord(StringRef Name, ArrayRef Filenames) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} + + void pushRegion(CounterMappingRegion Region, uint64_t Count) { + if (CountedRegions.empty()) + ExecutionCount = Count; + CountedRegions.emplace_back(Region, Count); + } }; /// \brief Iterator over Functions, optionally filtered to a single file. @@ -312,10 +339,22 @@ struct CoverageSegment { CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) : Line(Line), Col(Col), Count(0), HasCount(false), IsRegionEntry(IsRegionEntry) {} + + CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, + bool IsRegionEntry) + : Line(Line), Col(Col), Count(Count), HasCount(true), + IsRegionEntry(IsRegionEntry) {} + + friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { + return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) == + std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry); + } + void setCount(uint64_t NewCount) { Count = NewCount; HasCount = true; } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } }; @@ -363,7 +402,7 @@ class CoverageMapping { public: /// \brief Load the coverage mapping using the given readers. static ErrorOr> - load(ObjectFileCoverageMappingReader &CoverageReader, + load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader); /// \brief Load the coverage mapping from the given files. diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index 73b0248..6714366 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -15,20 +15,19 @@ #ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H #define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/CoverageMapping.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/FileSystem.h" - +#include "llvm/Support/MemoryBuffer.h" #include namespace llvm { namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; /// \brief Coverage mapping information for a single function. struct CoverageMappingRecord { @@ -42,15 +41,14 @@ struct CoverageMappingRecord { /// \brief A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator { - ObjectFileCoverageMappingReader *Reader; + CoverageMappingReader *Reader; CoverageMappingRecord Record; void increment(); public: CoverageMappingIterator() : Reader(nullptr) {} - CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) - : Reader(Reader) { + CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { increment(); } @@ -68,6 +66,14 @@ public: CoverageMappingRecord *operator->() { return &Record; } }; +class CoverageMappingReader { +public: + virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0; + CoverageMappingIterator begin() { return CoverageMappingIterator(this); } + CoverageMappingIterator end() { return CoverageMappingIterator(); } + virtual ~CoverageMappingReader() {} +}; + /// \brief Base class for the raw coverage mapping and filenames data readers. class RawCoverageReader { protected: @@ -91,10 +97,9 @@ protected: class RawCoverageFilenamesReader : public RawCoverageReader { std::vector &Filenames; - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) - LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageFilenamesReader &) = delete; public: RawCoverageFilenamesReader(StringRef Data, std::vector &Filenames) @@ -105,29 +110,27 @@ public: /// \brief Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { - StringRef FunctionName; ArrayRef TranslationUnitFilenames; std::vector &Filenames; std::vector &Expressions; std::vector &MappingRegions; - RawCoverageMappingReader(const RawCoverageMappingReader &) - LLVM_DELETED_FUNCTION; + RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageMappingReader &) = delete; public: - RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + RawCoverageMappingReader(StringRef MappingData, ArrayRef TranslationUnitFilenames, std::vector &Filenames, std::vector &Expressions, std::vector &MappingRegions) - : RawCoverageReader(MappingData), FunctionName(FunctionName), + : RawCoverageReader(MappingData), TranslationUnitFilenames(TranslationUnitFilenames), Filenames(Filenames), Expressions(Expressions), MappingRegions(MappingRegions) {} - std::error_code read(CoverageMappingRecord &Record); + std::error_code read(); private: std::error_code decodeCounter(unsigned Value, Counter &C); @@ -139,7 +142,7 @@ private: /// \brief Reader for the coverage mapping data that is emitted by the /// frontend and stored in an object file. -class ObjectFileCoverageMappingReader { +class BinaryCoverageReader : public CoverageMappingReader { public: struct ProfileMappingRecord { CoverageMappingVersion Version; @@ -158,8 +161,6 @@ public: }; private: - std::error_code LastError; - object::OwningBinary Object; std::vector Filenames; std::vector MappingRecords; size_t CurrentRecord; @@ -167,40 +168,16 @@ private: std::vector Expressions; std::vector MappingRegions; - ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) - LLVM_DELETED_FUNCTION; - ObjectFileCoverageMappingReader & - operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; - - /// \brief Set the current error_code and return same. - std::error_code error(std::error_code EC) { - LastError = EC; - return EC; - } + BinaryCoverageReader(const BinaryCoverageReader &) = delete; + BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } + BinaryCoverageReader() : CurrentRecord(0) {} public: - ObjectFileCoverageMappingReader(StringRef FileName); - ObjectFileCoverageMappingReader( - std::unique_ptr &ObjectBuffer, - sys::fs::file_magic Type = sys::fs::file_magic::unknown); - - std::error_code readHeader(); - std::error_code readNextRecord(CoverageMappingRecord &Record); - - /// Iterator over profile data. - CoverageMappingIterator begin() { return CoverageMappingIterator(this); } - CoverageMappingIterator end() { return CoverageMappingIterator(); } + static ErrorOr> + create(std::unique_ptr &ObjectBuffer); - /// \brief Return true if the reader has finished reading the profile data. - bool isEOF() { return LastError == instrprof_error::eof; } - /// \brief Return true if the reader encountered an error reading profiling - /// data. - bool hasError() { return LastError && !isEOF(); } - /// \brief Get the current error code. - std::error_code getError() { return LastError; } + std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; } // end namespace coverage diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/CoverageMappingWriter.h index cf16140..2e3b037 100644 --- a/include/llvm/ProfileData/CoverageMappingWriter.h +++ b/include/llvm/ProfileData/CoverageMappingWriter.h @@ -15,9 +15,9 @@ #ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H #define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H -#include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/CoverageMapping.h" #include "llvm/Support/raw_ostream.h" namespace llvm { diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 38c5310..63a6ac6 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -18,12 +18,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" - #include namespace llvm { @@ -96,6 +95,9 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. static ErrorOr> create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); }; /// Reader for the simple text based instrprof format. @@ -115,9 +117,8 @@ private: /// The current set of counter values. std::vector Counts; - TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - TextInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; public: TextInstrProfReader(std::unique_ptr DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} @@ -168,9 +169,8 @@ private: const char *NamesStart; const char *ProfileEnd; - RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const RawInstrProfReader &) - LLVM_DELETED_FUNCTION; + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) { } @@ -274,9 +274,8 @@ private: /// The maximal execution count among all functions. uint64_t MaxFunctionCount; - IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) - LLVM_DELETED_FUNCTION; + IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; public: IndexedInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} @@ -296,8 +295,11 @@ public: uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } /// Factory method to create an indexed reader. - static std::error_code - create(std::string Path, std::unique_ptr &Result); + static ErrorOr> + create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index e76f668..ce0bb52 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -20,8 +20,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" - #include namespace llvm { @@ -42,8 +42,13 @@ public: std::error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef Counters); - /// Ensure that all data is written to disk. + /// Write the profile to \c OS void write(raw_fd_ostream &OS); + /// Write the profile, returning the raw data. For testing. + std::unique_ptr writeBuffer(); + +private: + std::pair writeImpl(raw_ostream &OS); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index 5c70b31..df0a055 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -19,7 +19,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - #include namespace llvm { diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h index c20b815..c082a1a 100644 --- a/include/llvm/ProfileData/SampleProfReader.h +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -14,12 +14,12 @@ #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 07340de..96a8219 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -171,6 +171,8 @@ enum { WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 // Tag_ABI_FP_denormal, (=20), uleb128 + PositiveZero = 0, + IEEEDenormals = 1, PreserveFPSign = 2, // sign when flushed-to-zero is preserved // Tag_ABI_FP_number_model, (=23), uleb128 @@ -198,6 +200,9 @@ enum { // Tag_FP_HP_extension, (=36), uleb128 AllowHPFP = 1, // Allow use of Half Precision FP + // Tag_FP_16bit_format, (=38), uleb128 + FP16FormatIEEE = 1, + // Tag_MPextension_use, (=42), uleb128 AllowMP = 1, // Allow use of MP extensions diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 150bce5..7f54822 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -664,16 +664,16 @@ namespace COFF { } }; - enum CodeViewLineTableIdentifiers { - DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + enum CodeViewIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, + DEBUG_INDEX_SUBSECTION = 0xF4, // Symbol subsections are split into records of different types. DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index beed31a..6ba5efa 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -243,6 +243,26 @@ inline typename cast_retty::ret_type cast(Y *Val) { // accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(const Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type cast_or_null(Y *Val) { if (!Val) return nullptr; @@ -282,6 +302,20 @@ dyn_cast(Y *Val) { // value is accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(const Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type dyn_cast_or_null(Y *Val) { return (Val && isa(Val)) ? cast(Val) : nullptr; diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 2b5c9c5..64c5d96 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" @@ -40,7 +41,7 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, const char * const *argv, +void ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview = nullptr); //===----------------------------------------------------------------------===// @@ -66,25 +67,33 @@ void SetVersionPrinter(void (*func)()); /// information specific to the tool. void AddExtraVersionPrinter(void (*func)()); - // PrintOptionValues - Print option values. // With -print-options print the difference between option values and defaults. // With -print-all-options print all option values. // (Currently not perfect, but best-effort.) void PrintOptionValues(); -// MarkOptionsChanged - Internal helper function. -void MarkOptionsChanged(); +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); //===----------------------------------------------------------------------===// // Flags permitted to be passed to command line arguments // -enum NumOccurrencesFlag { // Flags for the number of occurrences allowed - Optional = 0x00, // Zero or One occurrence - ZeroOrMore = 0x01, // Zero or more occurrences allowed - Required = 0x02, // One occurrence required - OneOrMore = 0x03, // One or more occurrences required +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required // ConsumeAfter - Indicates that this option is fed anything that follows the // last positional argument required by the application (it is an error if @@ -93,20 +102,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed // found. Once a filename is found, all of the succeeding arguments are // passed, unprocessed, to the ConsumeAfter option. // - ConsumeAfter = 0x04 + ConsumeAfter = 0x04 }; -enum ValueExpected { // Is a value required for the option? +enum ValueExpected { // Is a value required for the option? // zero reserved for the unspecified value - ValueOptional = 0x01, // The value can appear... or not - ValueRequired = 0x02, // The value is required to appear! - ValueDisallowed = 0x03 // A value may not be specified (for flags) + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) }; -enum OptionHidden { // Control whether -help shows this option - NotHidden = 0x00, // Option included in -help & -help-hidden - Hidden = 0x01, // -help doesn't, but -help-hidden does - ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg }; // Formatting flags - This controls special features that the option might have @@ -125,16 +134,16 @@ enum OptionHidden { // Control whether -help shows this option // enum FormattingFlags { - NormalFormatting = 0x00, // Nothing special - Positional = 0x01, // Is a positional argument, no '-' required - Prefix = 0x02, // Can this option directly prefix its value? - Grouping = 0x03 // Can this option group with other options? + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? }; -enum MiscFlags { // Miscellaneous flags to adjust argument - CommaSeparated = 0x01, // Should this cl::list split between commas? - PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? - Sink = 0x04 // Should this cl::list eat all unknown options? +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? }; //===----------------------------------------------------------------------===// @@ -145,9 +154,13 @@ private: const char *const Name; const char *const Description; void registerCategory(); + public: - OptionCategory(const char *const Name, const char *const Description = nullptr) - : Name(Name), Description(Description) { registerCategory(); } + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } const char *getName() const { return Name; } const char *getDescription() const { return Description; } }; @@ -176,7 +189,7 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences; // The number of times specified + int NumOccurrences; // The number of times specified // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid // problems with signed enums in bitfields. unsigned Occurrences : 3; // enum NumOccurrencesFlag @@ -186,22 +199,21 @@ class Option { unsigned HiddenFlag : 2; // enum OptionHidden unsigned Formatting : 2; // enum FormattingFlags unsigned Misc : 3; - unsigned Position; // Position of last occurrence of the option - unsigned AdditionalVals;// Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. public: const char *ArgStr; // The argument string itself (ex: "help", "o") const char *HelpStr; // The descriptive text message for -help const char *ValueStr; // String describing what the value of this option is OptionCategory *Category; // The Category this option belongs to + bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { return (enum NumOccurrencesFlag)Occurrences; } inline enum ValueExpected getValueExpectedFlag() const { - return Value ? ((enum ValueExpected)Value) - : getValueExpectedFlagDefault(); + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); } inline enum OptionHidden getOptionHiddenFlag() const { return (enum OptionHidden)HiddenFlag; @@ -209,9 +221,7 @@ public: inline enum FormattingFlags getFormattingFlag() const { return (enum FormattingFlags)Formatting; } - inline unsigned getMiscFlags() const { - return Misc; - } + inline unsigned getMiscFlags() const { return Misc; } inline unsigned getPosition() const { return Position; } inline unsigned getNumAdditionalVals() const { return AdditionalVals; } @@ -221,28 +231,27 @@ public: //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers // - void setArgStr(const char *S) { ArgStr = S; } + void setArgStr(const char *S); void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } - void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { - Occurrences = Val; - } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } void setCategory(OptionCategory &C) { Category = &C; } + protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), - HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(nullptr), - ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { - } + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + public: // addArgument - Register this argument with the commandline system. // @@ -254,8 +263,6 @@ public: /// For testing purposes only. void removeArgument(); - Option *getNextRegisteredOption() const { return NextRegistered; } - // Return the width of the option tag for printing... virtual size_t getOptionWidth() const = 0; @@ -266,12 +273,12 @@ public: virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; - virtual void getExtraOptionNames(SmallVectorImpl &) {} + virtual void getExtraOptionNames(SmallVectorImpl &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - virtual bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -281,7 +288,6 @@ public: virtual ~Option() {} }; - //===----------------------------------------------------------------------===// // Command line option modifiers that can be used to modify the behavior of // command line option parsers... @@ -306,36 +312,31 @@ struct value_desc { // the default constructor for the argument type does not give you what you // want. This is only valid on "opt" arguments, not on "list" arguments. // -template -struct initializer { +template struct initializer { const Ty &Init; initializer(const Ty &Val) : Init(Val) {} - template - void apply(Opt &O) const { O.setInitialValue(Init); } + template void apply(Opt &O) const { O.setInitialValue(Init); } }; -template -initializer init(const Ty &Val) { +template initializer init(const Ty &Val) { return initializer(Val); } - // location - Allow the user to specify which external variable they want to // store the results of the command line argument processing into, if they don't // want to store it in the option itself. // -template -struct LocationClass { +template struct LocationClass { Ty &Loc; LocationClass(Ty &L) : Loc(L) {} - template - void apply(Opt &O) const { O.setLocation(O, Loc); } + template void apply(Opt &O) const { O.setLocation(O, Loc); } }; -template -LocationClass location(Ty &L) { return LocationClass(L); } +template LocationClass location(Ty &L) { + return LocationClass(L); +} // cat - Specifiy the Option category for the command line argument to belong // to. @@ -343,11 +344,9 @@ struct cat { OptionCategory &Category; cat(OptionCategory &c) : Category(c) {} - template - void apply(Opt &O) const { O.setCategory(Category); } + template void apply(Opt &O) const { O.setCategory(Category); } }; - //===----------------------------------------------------------------------===// // OptionValue class @@ -360,11 +359,11 @@ private: virtual void anchor(); }; -template struct OptionValue; +template struct OptionValue; // The default value safely does nothing. Option value printing is only // best-effort. -template +template struct OptionValueBase : public GenericOptionValue { // Temporary storage for argument passing. typedef OptionValue WrapperType; @@ -374,21 +373,20 @@ struct OptionValueBase : public GenericOptionValue { const DataType &getValue() const { llvm_unreachable("no default value"); } // Some options may take their value from a different data type. - template - void setValue(const DT& /*V*/) {} + template void setValue(const DT & /*V*/) {} - bool compare(const DataType &/*V*/) const { return false; } + bool compare(const DataType & /*V*/) const { return false; } - bool compare(const GenericOptionValue& /*V*/) const override { + bool compare(const GenericOptionValue & /*V*/) const override { return false; } }; // Simple copy of the option value. -template -class OptionValueCopy : public GenericOptionValue { +template class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; + public: OptionValueCopy() : Valid(false) {} @@ -399,37 +397,36 @@ public: return Value; } - void setValue(const DataType &V) { Valid = true; Value = V; } - - bool compare(const DataType &V) const { - return Valid && (Value != V); + void setValue(const DataType &V) { + Valid = true; + Value = V; } + bool compare(const DataType &V) const { return Valid && (Value != V); } + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy &VC = - static_cast< const OptionValueCopy& >(V); - if (!VC.hasValue()) return false; + static_cast &>(V); + if (!VC.hasValue()) + return false; return compare(VC.getValue()); } }; // Non-class option values. -template +template struct OptionValueBase : OptionValueCopy { typedef DataType WrapperType; }; // Top-level option class. -template +template struct OptionValue : OptionValueBase::value> { OptionValue() {} - OptionValue(const DataType& V) { - this->setValue(V); - } + OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. - template - OptionValue &operator=(const DT& V) { + template OptionValue &operator=(const DT &V) { this->setValue(V); return *this; } @@ -437,36 +434,33 @@ struct OptionValue : OptionValueBase::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; -template<> +template <> struct OptionValue : OptionValueCopy { typedef cl::boolOrDefault WrapperType; OptionValue() {} - OptionValue(const cl::boolOrDefault& V) { - this->setValue(V); - } - OptionValue &operator=(const cl::boolOrDefault& V) { + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue &operator=(const cl::boolOrDefault &V) { setValue(V); return *this; } + private: void anchor() override; }; -template<> -struct OptionValue : OptionValueCopy { +template <> struct OptionValue : OptionValueCopy { typedef StringRef WrapperType; OptionValue() {} - OptionValue(const std::string& V) { - this->setValue(V); - } - OptionValue &operator=(const std::string& V) { + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue &operator=(const std::string &V) { setValue(V); return *this; } + private: void anchor() override; }; @@ -476,20 +470,20 @@ private: // #define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC #define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC -#define clEnumValEnd (reinterpret_cast(0)) +#define clEnumValEnd (reinterpret_cast(0)) // values - For custom data types, allow specifying a group of values together // as the values that go into the mapping that the option handler uses. Note // that the values list must always have a 0 at the end of the list to indicate // that the list has ended. // -template -class ValuesClass { +template class ValuesClass { // Use a vector instead of a map, because the lists should be short, // the overhead is less, and most importantly, it keeps them in the order // inserted so we can print our option out nicely. - SmallVector >,4> Values; + SmallVector>, 4> Values; void processValues(va_list Vals); + public: ValuesClass(const char *EnumName, DataType Val, const char *Desc, va_list ValueArgs) { @@ -500,13 +494,12 @@ public: while (const char *enumName = va_arg(ValueArgs, const char *)) { DataType EnumVal = static_cast(va_arg(ValueArgs, int)); const char *EnumDesc = va_arg(ValueArgs, const char *); - Values.push_back(std::make_pair(enumName, // Add value to value map + Values.push_back(std::make_pair(enumName, // Add value to value map std::make_pair(EnumVal, EnumDesc))); } } - template - void apply(Opt &O) const { + template void apply(Opt &O) const { for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); @@ -516,11 +509,11 @@ public: template ValuesClass LLVM_END_WITH_NULL values(const char *Arg, DataType Val, const char *Desc, ...) { - va_list ValueArgs; - va_start(ValueArgs, Desc); - ValuesClass Vals(Arg, Val, Desc, ValueArgs); - va_end(ValueArgs); - return Vals; + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; } //===----------------------------------------------------------------------===// @@ -539,13 +532,16 @@ class generic_parser_base { protected: class GenericOptionInfo { public: - GenericOptionInfo(const char *name, const char *helpStr) : - Name(name), HelpStr(helpStr) {} + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} const char *Name; const char *HelpStr; }; + public: - virtual ~generic_parser_base() {} // Base class should have virtual-dtor + generic_parser_base(Option &O) : Owner(O) {} + + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to // indicate how many entries are in Values. @@ -576,30 +572,24 @@ public: // // Template definition ensures that the option and default have the same // DataType (via the same AnyOptionValue). - template + template void printOptionDiff(const Option &O, const AnyOptionValue &V, const AnyOptionValue &Default, size_t GlobalWidth) const { printGenericOptionDiff(O, V, Default, GlobalWidth); } - void initialize(Option &O) { - // All of the modifiers for the option have been processed by now, so the - // argstr field should be stable, copy it down now. - // - hasArgStr = O.hasArgStr(); - } + void initialize() {} - void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void getExtraOptionNames(SmallVectorImpl &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. - if (!hasArgStr) + if (!Owner.hasArgStr()) for (unsigned i = 0, e = getNumOptions(); i != e; ++i) OptionNames.push_back(getOption(i)); } - enum ValueExpected getValueExpectedFlagDefault() const { // If there is an ArgStr specified, then we are of the form: // @@ -612,7 +602,7 @@ public: // // If this is the case, we cannot allow a value. // - if (hasArgStr) + if (Owner.hasArgStr()) return ValueRequired; else return ValueDisallowed; @@ -624,7 +614,7 @@ public: unsigned findOption(const char *Name); protected: - bool hasArgStr; + Option &Owner; }; // Default parser implementation - This implementation depends on having a @@ -633,17 +623,18 @@ protected: // command line option for -help. Because this is a simple mapping parser, the // data type can be any unsupported type. // -template -class parser : public generic_parser_base { +template class parser : public generic_parser_base { protected: class OptionInfo : public GenericOptionInfo { public: - OptionInfo(const char *name, DataType v, const char *helpStr) : - GenericOptionInfo(name, helpStr), V(v) {} + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} OptionValue V; }; SmallVector Values; + public: + parser(Option &O) : generic_parser_base(O) {} typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base @@ -661,7 +652,7 @@ public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; - if (hasArgStr) + if (Owner.hasArgStr()) ArgVal = Arg; else ArgVal = ArgName; @@ -682,7 +673,7 @@ public: assert(findOption(Name) == Values.size() && "Option already exists!"); OptionInfo X(Name, static_cast(V), HelpStr); Values.push_back(X); - MarkOptionsChanged(); + AddLiteralOption(Owner, Name); } /// removeLiteralOption - Remove the specified option. @@ -690,24 +681,26 @@ public: void removeLiteralOption(const char *Name) { unsigned N = findOption(Name); assert(N != Values.size() && "Option not found!"); - Values.erase(Values.begin()+N); + Values.erase(Values.begin() + N); } }; //-------------------------------------------------- // basic_parser - Super class of parsers to provide boilerplate code // -class basic_parser_impl { // non-template implementation of basic_parser +class basic_parser_impl { // non-template implementation of basic_parser public: + basic_parser_impl(Option &O) {} + virtual ~basic_parser_impl() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; } - void getExtraOptionNames(SmallVectorImpl &) {} + void getExtraOptionNames(SmallVectorImpl &) {} - void initialize(Option &) {} + void initialize() {} // Return the width of the option tag for printing... size_t getOptionWidth(const Option &O) const; @@ -735,9 +728,9 @@ protected: // basic_parser - The real basic parser is just a template wrapper that provides // a typedef for the provided data type. // -template -class basic_parser : public basic_parser_impl { +template class basic_parser : public basic_parser_impl { public: + basic_parser(Option &O) : basic_parser_impl(O) {} typedef DataType parser_data_type; typedef OptionValue OptVal; }; @@ -745,18 +738,14 @@ public: //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { - const char *ArgStr; +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template - void initialize(Opt &O) { - ArgStr = O.ArgStr; - } + void initialize() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -776,9 +765,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -801,9 +791,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -819,13 +810,13 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); - //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -844,9 +835,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long long &Val); @@ -866,9 +859,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -887,9 +881,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -908,9 +903,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { Value = Arg.str(); @@ -932,9 +928,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { Value = Arg[0]; @@ -960,7 +957,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); // parser to handle all the template nastiness. // This overloaded function is selected by the generic parser. -template +template void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { OptionValue
OV = V; @@ -969,18 +966,16 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. -template -struct OptionDiffPrinter { - void print(const Option &O, const parser P, const ValDT &/*V*/, - const OptionValue &/*Default*/, size_t GlobalWidth) { +template struct OptionDiffPrinter { + void print(const Option &O, const parser P, const ValDT & /*V*/, + const OptionValue & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } }; // This is instantiated for basic parsers when the parsed value has the same // type as the option value. -template -struct OptionDiffPrinter { +template struct OptionDiffPrinter { void print(const Option &O, const parser
P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); @@ -989,15 +984,14 @@ struct OptionDiffPrinter { // This overloaded function is selected by the basic parser, which may parse a // different type than the option type. -template +template void printOptionDiff( - const Option &O, - const basic_parser &P, - const ValDT &V, const OptionValue &Default, - size_t GlobalWidth) { + const Option &O, + const basic_parser &P, + const ValDT &V, const OptionValue &Default, size_t GlobalWidth) { OptionDiffPrinter printer; - printer.print(O, static_cast(P), V, Default, + printer.print(O, static_cast(P), V, Default, GlobalWidth); } @@ -1007,46 +1001,53 @@ void printOptionDiff( // not correctly respond to the apply method). Because the syntax to use this // is a pain, we have the 'apply' method below to handle the nastiness... // -template struct applicator { - template - static void opt(const Mod &M, Opt &O) { M.apply(O); } +template struct applicator { + template static void opt(const Mod &M, Opt &O) { M.apply(O); } }; // Handle const char* as a special case... -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <> struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { +template <> struct applicator { static void opt(NumOccurrencesFlag N, Option &O) { O.setNumOccurrencesFlag(N); } }; -template<> struct applicator { +template <> struct applicator { static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } }; -template<> struct applicator { +template <> struct applicator { static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } }; -template<> struct applicator { +template <> struct applicator { static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } }; -template<> struct applicator { +template <> struct applicator { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; -// apply method - Apply a modifier to an option in a type safe way. -template -void apply(const Mod &M, Opt *O) { +// apply method - Apply modifiers to an option in a type safe way. +template +void apply(Opt *O, const Mod &M, const Mods &... Ms) { + applicator::opt(M, *O); + apply(O, Ms...); +} + +template void apply(Opt *O, const Mod &M) { applicator::opt(M, *O); } @@ -1057,16 +1058,17 @@ void apply(const Mod &M, Opt *O) { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template +template class opt_storage { - DataType *Location; // Where to store the object... + DataType *Location; // Where to store the object... OptionValue Default; void check_location() const { assert(Location && "cl::location(...) not specified for a command " - "line option with external storage, " - "or cl::init specified before cl::location()!!"); + "line option with external storage, " + "or cl::init specified before cl::location()!!"); } + public: opt_storage() : Location(nullptr) {} @@ -1078,16 +1080,21 @@ public: return false; } - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check_location(); return *Location; } - const DataType &getValue() const { check_location(); return *Location; } + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; + } operator DataType() const { return this->getValue(); } @@ -1098,13 +1105,12 @@ public: // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template -class opt_storage : public DataType { +template +class opt_storage : public DataType { public: OptionValue Default; - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { DataType::operator=(V); if (initial) Default = V; @@ -1120,8 +1126,7 @@ public: // this case, we store an instance through containment, and overload operators // to get at the value. // -template -class opt_storage { +template class opt_storage { public: DataType Value; OptionValue Default; @@ -1130,8 +1135,7 @@ public: // type. opt_storage() : Value(DataType()), Default(DataType()) {} - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { Value = V; if (initial) Default = V; @@ -1147,12 +1151,11 @@ public: DataType operator->() const { return Value; } }; - //===----------------------------------------------------------------------===// // opt - A scalar command line option. // template > + class ParserClass = parser> class opt : public Option, public opt_storage::value> { @@ -1161,9 +1164,9 @@ class opt : public Option, bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse error! + return true; // Parse error! this->setValue(Val); this->setPosition(pos); return false; @@ -1172,102 +1175,50 @@ class opt : public Option, enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { - cl::printOptionDiff( - *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); + cl::printOptionDiff(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); } } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } - template - DataType &operator=(const T &Val) { + template DataType &operator=(const T &Val) { this->setValue(Val); return this->getValue(); } - // One option... - template - explicit opt(const M0t &M0) : Option(Optional, NotHidden) { - apply(M0, this); - done(); - } - - // Two options... - template - opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - - // Three options... - template - opt(const M0t &M0, const M1t &M1, - const M2t &M2) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, - const M3t &M3) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, - const M6t &M6) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1285,9 +1236,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt); // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class list_storage { - StorageClass *Location; // Where to store the object... +template class list_storage { + StorageClass *Location; // Where to store the object... public: list_storage() : Location(0) {} @@ -1299,32 +1249,30 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); Location->push_back(V); } }; - // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template +template class list_storage : public std::vector { public: - template - void addValue(const T &V) { std::vector::push_back(V); } + template void addValue(const T &V) { + std::vector::push_back(V); + } }; - //===----------------------------------------------------------------------===// // list - A list of command line options. // template > + class ParserClass = parser> class list : public Option, public list_storage { std::vector Positions; ParserClass Parser; @@ -1332,16 +1280,17 @@ class list : public Option, public list_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! list_storage::addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1349,19 +1298,26 @@ class list : public Option, public list_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1370,71 +1326,12 @@ public: return Positions[optnum]; } - void setNumAdditionalVals(unsigned n) { - Option::setNumAdditionalVals(n); - } + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } - // One option... - template - explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1445,10 +1342,11 @@ struct multi_val { explicit multi_val(unsigned N) : AdditionalVals(N) {} template - void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } + void apply(list &L) const { + L.setNumAdditionalVals(AdditionalVals); + } }; - //===----------------------------------------------------------------------===// // bits_storage class @@ -1456,15 +1354,13 @@ struct multi_val { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class bits_storage { - unsigned *Location; // Where to store the bits... +template class bits_storage { + unsigned *Location; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = reinterpret_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } @@ -1478,57 +1374,45 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); *Location |= Bit(V); } unsigned getBits() { return *Location; } - template - bool isSet(const T &V) { + template bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } }; - // Define how to hold bits. Since we can inherit from a class, we do so. // This makes us exactly compatible with the bits in all cases that it is used. // -template -class bits_storage { - unsigned Bits; // Where to store the bits... +template class bits_storage { + unsigned Bits; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = (unsigned)V; assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - template - void addValue(const T &V) { - Bits |= Bit(V); - } + template void addValue(const T &V) { Bits |= Bit(V); } unsigned getBits() { return Bits; } - template - bool isSet(const T &V) { - return (Bits & Bit(V)) != 0; - } + template bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; - //===----------------------------------------------------------------------===// // bits - A bit vector of command options. // template > + class ParserClass = parser> class bits : public Option, public bits_storage { std::vector Positions; ParserClass Parser; @@ -1536,16 +1420,17 @@ class bits : public Option, public bits_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! this->addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1553,19 +1438,26 @@ class bits : public Option, public bits_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1574,67 +1466,10 @@ public: return Positions[optnum]; } - // One option... - template - explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1646,11 +1481,11 @@ public: class alias : public Option { Option *AliasFor; bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) override { + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } - bool addOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Value, bool MultiArg = false) override { + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); } // Handle printing stuff... @@ -1658,8 +1493,8 @@ class alias : public Option { void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } ValueExpected getValueExpectedFlagDefault() const override { return AliasFor->getValueExpectedFlag(); @@ -1670,8 +1505,13 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); - addArgument(); + addArgument(); } + + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1679,31 +1519,10 @@ public: AliasFor = &O; } - // One option... - template - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - done(); - } - // Two options... - template - alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template + explicit alias(const Mods &... Ms) + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(this, Ms...); done(); } }; @@ -1720,8 +1539,8 @@ struct aliasopt { // printed to stderr at the end of the regular help, just before // exit is called. struct extrahelp { - const char * morehelp; - explicit extrahelp(const char* help); + const char *morehelp; + explicit extrahelp(const char *help); }; void PrintVersionMessage(); @@ -1733,8 +1552,7 @@ void PrintVersionMessage(); /// /// \param Hidden if true will print hidden options /// \param Categorized if true print options in categories -void PrintHelpMessage(bool Hidden=false, bool Categorized=false); - +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. @@ -1743,9 +1561,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// -/// \param [out] Map will be filled with mappings where the key is the -/// Option argument string (e.g. "help") and value is the corresponding -/// Option*. +/// \return A reference to the StringMap used by the cl APIs to parse options. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. @@ -1753,8 +1569,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// Typical usage: /// \code /// main(int argc,char* argv[]) { -/// StringMap opts; -/// llvm::cl::getRegisteredOptions(opts); +/// StringMap &opts = llvm::cl::getRegisteredOptions(); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code @@ -1766,7 +1581,11 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap &Map); +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap