aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
committerStephen Hines <srhines@google.com>2015-03-23 12:10:34 -0700
commitebe69fe11e48d322045d5949c83283927a0d790b (patch)
treec92f1907a6b8006628a4b01615f38264d29834ea /include
parentb7d2e72b02a4cb8034f32f8247a2558d2434e121 (diff)
downloadexternal_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.zip
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.gz
external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.bz2
Update aosp/master LLVM for rebase to r230699.
Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9
Diffstat (limited to 'include')
-rw-r--r--include/llvm-c/Core.h5
-rw-r--r--include/llvm-c/ExecutionEngine.h4
-rw-r--r--include/llvm-c/Linker.h9
-rw-r--r--include/llvm-c/Transforms/Scalar.h3
-rw-r--r--include/llvm-c/lto.h48
-rw-r--r--include/llvm/ADT/APFloat.h2
-rw-r--r--include/llvm/ADT/APInt.h15
-rw-r--r--include/llvm/ADT/APSInt.h73
-rw-r--r--include/llvm/ADT/ArrayRef.h2
-rw-r--r--include/llvm/ADT/BitVector.h42
-rw-r--r--include/llvm/ADT/DenseMap.h207
-rw-r--r--include/llvm/ADT/DenseSet.h35
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h2
-rw-r--r--include/llvm/ADT/EquivalenceClasses.h3
-rw-r--r--include/llvm/ADT/FoldingSet.h74
-rw-r--r--include/llvm/ADT/Hashing.h104
-rw-r--r--include/llvm/ADT/ImmutableList.h4
-rw-r--r--include/llvm/ADT/ImmutableMap.h4
-rw-r--r--include/llvm/ADT/ImmutableSet.h4
-rw-r--r--include/llvm/ADT/IntervalMap.h2
-rw-r--r--include/llvm/ADT/IntrusiveRefCntPtr.h6
-rw-r--r--include/llvm/ADT/MapVector.h9
-rw-r--r--include/llvm/ADT/None.h5
-rw-r--r--include/llvm/ADT/Optional.h49
-rw-r--r--include/llvm/ADT/PointerUnion.h80
-rw-r--r--include/llvm/ADT/STLExtras.h280
-rw-r--r--include/llvm/ADT/ScopedHashTable.h4
-rw-r--r--include/llvm/ADT/SmallBitVector.h28
-rw-r--r--include/llvm/ADT/SmallPtrSet.h10
-rw-r--r--include/llvm/ADT/SmallVector.h53
-rw-r--r--include/llvm/ADT/SparseBitVector.h34
-rw-r--r--include/llvm/ADT/SparseMultiSet.h4
-rw-r--r--include/llvm/ADT/SparseSet.h4
-rw-r--r--include/llvm/ADT/StringMap.h15
-rw-r--r--include/llvm/ADT/StringRef.h7
-rw-r--r--include/llvm/ADT/TinyPtrVector.h22
-rw-r--r--include/llvm/ADT/Triple.h55
-rw-r--r--include/llvm/ADT/Twine.h14
-rw-r--r--include/llvm/ADT/ilist.h12
-rw-r--r--include/llvm/ADT/iterator.h2
-rw-r--r--include/llvm/ADT/iterator_range.h1
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h27
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h4
-rw-r--r--include/llvm/Analysis/AssumptionCache.h183
-rw-r--r--include/llvm/Analysis/AssumptionTracker.h128
-rw-r--r--include/llvm/Analysis/BranchProbabilityInfo.h4
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h192
-rw-r--r--include/llvm/Analysis/CallGraph.h4
-rw-r--r--include/llvm/Analysis/CodeMetrics.h10
-rw-r--r--include/llvm/Analysis/DependenceAnalysis.h4
-rw-r--r--include/llvm/Analysis/FindUsedTypes.h66
-rw-r--r--include/llvm/Analysis/FunctionTargetTransformInfo.h49
-rw-r--r--include/llvm/Analysis/InlineCost.h10
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h99
-rw-r--r--include/llvm/Analysis/JumpInstrTableInfo.h1
-rw-r--r--include/llvm/Analysis/LazyCallGraph.h14
-rw-r--r--include/llvm/Analysis/LazyValueInfo.h29
-rw-r--r--include/llvm/Analysis/LibCallSemantics.h23
-rw-r--r--include/llvm/Analysis/LoopAccessAnalysis.h290
-rw-r--r--include/llvm/Analysis/LoopInfo.h202
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h19
-rw-r--r--include/llvm/Analysis/MemoryDependenceAnalysis.h24
-rw-r--r--include/llvm/Analysis/PHITransAddr.h10
-rw-r--r--include/llvm/Analysis/Passes.h8
-rw-r--r--include/llvm/Analysis/RegionInfo.h12
-rw-r--r--include/llvm/Analysis/RegionInfoImpl.h2
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h30
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h2
-rw-r--r--include/llvm/Analysis/SparsePropagation.h4
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h (renamed from include/llvm/Target/TargetLibraryInfo.h)214
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h637
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h433
-rw-r--r--include/llvm/Analysis/ValueTracking.h36
-rw-r--r--include/llvm/Bitcode/BitCodes.h2
-rw-r--r--include/llvm/Bitcode/BitcodeWriterPass.h2
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h24
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h41
-rw-r--r--include/llvm/Bitcode/ReaderWriter.h70
-rw-r--r--include/llvm/CodeGen/Analysis.h17
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h54
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h723
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h63
-rw-r--r--include/llvm/CodeGen/CommandFlags.h5
-rw-r--r--include/llvm/CodeGen/DIE.h587
-rw-r--r--include/llvm/CodeGen/FastISel.h11
-rw-r--r--include/llvm/CodeGen/ForwardControlFlowIntegrity.h1
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h16
-rw-r--r--include/llvm/CodeGen/GCMetadata.h295
-rw-r--r--include/llvm/CodeGen/GCMetadataPrinter.h76
-rw-r--r--include/llvm/CodeGen/GCStrategy.h254
-rw-r--r--include/llvm/CodeGen/GCs.h32
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h23
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h18
-rw-r--r--include/llvm/CodeGen/LinkAllCodegenComponents.h1
-rw-r--r--include/llvm/CodeGen/LiveInterval.h226
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h57
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h14
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h4
-rw-r--r--include/llvm/CodeGen/MachineDominanceFrontier.h4
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineFunction.h22
-rw-r--r--include/llvm/CodeGen/MachineInstr.h25
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h37
-rw-r--r--include/llvm/CodeGen/MachinePassRegistry.h7
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h19
-rw-r--r--include/llvm/CodeGen/MachineSSAUpdater.h4
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h1
-rw-r--r--include/llvm/CodeGen/MachineValueType.h64
-rw-r--r--include/llvm/CodeGen/PBQP/Graph.h73
-rw-r--r--include/llvm/CodeGen/PBQP/ReductionRules.h32
-rw-r--r--include/llvm/CodeGen/Passes.h86
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h132
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h6
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h14
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h2
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h127
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h2
-rw-r--r--include/llvm/CodeGen/StackMaps.h50
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h11
-rw-r--r--include/llvm/CodeGen/ValueTypes.td3
-rw-r--r--include/llvm/CodeGen/VirtRegMap.h4
-rw-r--r--include/llvm/Config/config.h.cmake24
-rw-r--r--include/llvm/Config/config.h.in15
-rw-r--r--include/llvm/Config/llvm-config.h.cmake7
-rw-r--r--include/llvm/Config/llvm-config.h.in3
-rw-r--r--include/llvm/DebugInfo/DWARF/DIContext.h (renamed from include/llvm/DebugInfo/DIContext.h)1
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h60
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h49
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h31
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h292
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h63
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h70
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h87
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h43
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h160
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLine.h238
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h81
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h77
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h (renamed from include/llvm/DebugInfo/DWARFFormValue.h)0
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFRelocMap.h22
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFSection.h24
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h38
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h285
-rw-r--r--include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h59
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIADataStream.h33
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h35
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h35
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h37
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h37
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h39
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h206
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASession.h42
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h36
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASupport.h33
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBDataStream.h37
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBEnumChildren.h33
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBLineNumber.h36
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBRawSymbol.h211
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSession.h56
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSourceFile.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDB.h23
-rw-r--r--include/llvm/DebugInfo/PDB/PDBExtras.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymDumper.h85
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbol.h98
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolBlock.h41
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h38
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h55
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCustom.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolData.h61
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolExe.h46
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFunc.h80
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolLabel.h49
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h47
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolThunk.h57
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h45
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h60
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h40
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h52
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h50
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h35
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h43
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h54
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h52
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h40
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h39
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h34
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h36
-rw-r--r--include/llvm/DebugInfo/PDB/PDBTypes.h479
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h39
-rw-r--r--include/llvm/ExecutionEngine/JITEventListener.h19
-rw-r--r--include/llvm/ExecutionEngine/ObjectBuffer.h76
-rw-r--r--include/llvm/ExecutionEngine/ObjectImage.h76
-rw-r--r--include/llvm/ExecutionEngine/ObjectMemoryBuffer.h63
-rw-r--r--include/llvm/ExecutionEngine/Orc/CloneSubModule.h60
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h355
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileUtils.h62
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRCompileLayer.h146
-rw-r--r--include/llvm/ExecutionEngine/Orc/IndirectionUtils.h246
-rw-r--r--include/llvm/ExecutionEngine/Orc/JITSymbol.h74
-rw-r--r--include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h283
-rw-r--r--include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h92
-rw-r--r--include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h267
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h56
-rw-r--r--include/llvm/ExecutionEngine/OrcMCJITReplacement.h38
-rw-r--r--include/llvm/ExecutionEngine/RTDyldMemoryManager.h32
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h55
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyldChecker.h1
-rw-r--r--include/llvm/ExecutionEngine/SectionMemoryManager.h4
-rw-r--r--include/llvm/IR/Attributes.h5
-rw-r--r--include/llvm/IR/BasicBlock.h12
-rw-r--r--include/llvm/IR/CFG.h26
-rw-r--r--include/llvm/IR/CallSite.h2
-rw-r--r--include/llvm/IR/Comdat.h2
-rw-r--r--include/llvm/IR/Constant.h4
-rw-r--r--include/llvm/IR/ConstantRange.h95
-rw-r--r--include/llvm/IR/Constants.h64
-rw-r--r--include/llvm/IR/DIBuilder.h118
-rw-r--r--include/llvm/IR/DataLayout.h7
-rw-r--r--include/llvm/IR/DebugInfo.h293
-rw-r--r--include/llvm/IR/DebugInfoFlags.def36
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h1669
-rw-r--r--include/llvm/IR/DebugLoc.h98
-rw-r--r--include/llvm/IR/DerivedTypes.h30
-rw-r--r--include/llvm/IR/DiagnosticInfo.h3
-rw-r--r--include/llvm/IR/Dominators.h49
-rw-r--r--include/llvm/IR/Function.h42
-rw-r--r--include/llvm/IR/GVMaterializer.h4
-rw-r--r--include/llvm/IR/GlobalAlias.h4
-rw-r--r--include/llvm/IR/GlobalObject.h2
-rw-r--r--include/llvm/IR/GlobalValue.h3
-rw-r--r--include/llvm/IR/GlobalVariable.h6
-rw-r--r--include/llvm/IR/IRBuilder.h71
-rw-r--r--include/llvm/IR/IRPrintingPasses.h4
-rw-r--r--include/llvm/IR/InlineAsm.h4
-rw-r--r--include/llvm/IR/InstIterator.h12
-rw-r--r--include/llvm/IR/InstrTypes.h32
-rw-r--r--include/llvm/IR/Instruction.h6
-rw-r--r--include/llvm/IR/Instructions.h37
-rw-r--r--include/llvm/IR/IntrinsicInst.h54
-rw-r--r--include/llvm/IR/Intrinsics.h30
-rw-r--r--include/llvm/IR/Intrinsics.td69
-rw-r--r--include/llvm/IR/IntrinsicsBPF.td22
-rw-r--r--include/llvm/IR/IntrinsicsHexagon.td319
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td177
-rw-r--r--include/llvm/IR/IntrinsicsR600.td3
-rw-r--r--include/llvm/IR/IntrinsicsX86.td581
-rw-r--r--include/llvm/IR/LLVMContext.h4
-rw-r--r--include/llvm/IR/LeakDetector.h92
-rw-r--r--include/llvm/IR/LegacyPassManager.h12
-rw-r--r--include/llvm/IR/LegacyPassManagers.h9
-rw-r--r--include/llvm/IR/LegacyPassNameParser.h10
-rw-r--r--include/llvm/IR/MDBuilder.h8
-rw-r--r--include/llvm/IR/Metadata.def99
-rw-r--r--include/llvm/IR/Metadata.h947
-rw-r--r--include/llvm/IR/MetadataTracking.h99
-rw-r--r--include/llvm/IR/Module.h55
-rw-r--r--include/llvm/IR/Operator.h22
-rw-r--r--include/llvm/IR/PassManager.h808
-rw-r--r--include/llvm/IR/PassManagerInternal.h349
-rw-r--r--include/llvm/IR/PatternMatch.h751
-rw-r--r--include/llvm/IR/Statepoint.h298
-rw-r--r--include/llvm/IR/TrackingMDRef.h170
-rw-r--r--include/llvm/IR/Type.h3
-rw-r--r--include/llvm/IR/TypeFinder.h1
-rw-r--r--include/llvm/IR/Use.h2
-rw-r--r--include/llvm/IR/UseListOrder.h4
-rw-r--r--include/llvm/IR/User.h4
-rw-r--r--include/llvm/IR/Value.h64
-rw-r--r--include/llvm/IR/ValueHandle.h98
-rw-r--r--include/llvm/IR/ValueMap.h36
-rw-r--r--include/llvm/IR/Verifier.h4
-rw-r--r--include/llvm/InitializePasses.h32
-rw-r--r--include/llvm/LTO/LTOCodeGenerator.h22
-rw-r--r--include/llvm/LinkAllPasses.h9
-rw-r--r--include/llvm/Linker/Linker.h82
-rw-r--r--include/llvm/MC/MCAsmBackend.h18
-rw-r--r--include/llvm/MC/MCAsmInfo.h41
-rw-r--r--include/llvm/MC/MCAsmInfoDarwin.h2
-rw-r--r--include/llvm/MC/MCAssembler.h18
-rw-r--r--include/llvm/MC/MCCodeEmitter.h4
-rw-r--r--include/llvm/MC/MCContext.h16
-rw-r--r--include/llvm/MC/MCDwarf.h6
-rw-r--r--include/llvm/MC/MCELFObjectWriter.h1
-rw-r--r--include/llvm/MC/MCExpr.h5
-rw-r--r--include/llvm/MC/MCInst.h22
-rw-r--r--include/llvm/MC/MCInstPrinter.h10
-rw-r--r--include/llvm/MC/MCInstrDesc.h11
-rw-r--r--include/llvm/MC/MCLabel.h4
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h2
-rw-r--r--include/llvm/MC/MCMachObjectWriter.h28
-rw-r--r--include/llvm/MC/MCObjectWriter.h10
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h4
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h4
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h4
-rw-r--r--include/llvm/MC/MCParser/MCAsmParserExtension.h4
-rw-r--r--include/llvm/MC/MCRegisterInfo.h72
-rw-r--r--include/llvm/MC/MCRelocationInfo.h4
-rw-r--r--include/llvm/MC/MCSection.h4
-rw-r--r--include/llvm/MC/MCSectionELF.h14
-rw-r--r--include/llvm/MC/MCStreamer.h14
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h15
-rw-r--r--include/llvm/MC/MCSymbol.h22
-rw-r--r--include/llvm/MC/MCSymbolizer.h4
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h5
-rw-r--r--include/llvm/MC/MCTargetOptions.h12
-rw-r--r--include/llvm/MC/MCTargetOptionsCommandFlags.h8
-rw-r--r--include/llvm/MC/MCValue.h2
-rw-r--r--include/llvm/MC/MCWinCOFFObjectWriter.h15
-rw-r--r--include/llvm/MC/SectionKind.h6
-rw-r--r--include/llvm/Object/Archive.h22
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFF.h14
-rw-r--r--include/llvm/Object/ELFObjectFile.h66
-rw-r--r--include/llvm/Object/ELFTypes.h52
-rw-r--r--include/llvm/Object/ELFYAML.h33
-rw-r--r--include/llvm/Object/IRObjectFile.h10
-rw-r--r--include/llvm/Object/MachO.h30
-rw-r--r--include/llvm/Object/MachOUniversal.h8
-rw-r--r--include/llvm/Object/ObjectFile.h27
-rw-r--r--include/llvm/Object/SymbolicFile.h5
-rw-r--r--include/llvm/Option/Arg.h4
-rw-r--r--include/llvm/Option/ArgList.h4
-rw-r--r--include/llvm/Option/OptSpecifier.h2
-rw-r--r--include/llvm/Pass.h4
-rw-r--r--include/llvm/PassAnalysisSupport.h2
-rw-r--r--include/llvm/PassInfo.h4
-rw-r--r--include/llvm/PassManager.h39
-rw-r--r--include/llvm/ProfileData/CoverageMapping.h85
-rw-r--r--include/llvm/ProfileData/CoverageMappingReader.h81
-rw-r--r--include/llvm/ProfileData/CoverageMappingWriter.h2
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h28
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h9
-rw-r--r--include/llvm/ProfileData/SampleProf.h1
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h6
-rw-r--r--include/llvm/Support/ARMBuildAttributes.h5
-rw-r--r--include/llvm/Support/COFF.h12
-rw-r--r--include/llvm/Support/Casting.h34
-rw-r--r--include/llvm/Support/CommandLine.h854
-rw-r--r--include/llvm/Support/Compiler.h91
-rw-r--r--include/llvm/Support/Compression.h2
-rw-r--r--include/llvm/Support/ConvertUTF.h8
-rw-r--r--include/llvm/Support/CrashRecoveryContext.h3
-rw-r--r--include/llvm/Support/Dwarf.def351
-rw-r--r--include/llvm/Support/Dwarf.h333
-rw-r--r--include/llvm/Support/ELF.h806
-rw-r--r--include/llvm/Support/ELFRelocs/AArch64.def147
-rw-r--r--include/llvm/Support/ELFRelocs/ARM.def138
-rw-r--r--include/llvm/Support/ELFRelocs/Hexagon.def92
-rw-r--r--include/llvm/Support/ELFRelocs/Mips.def112
-rw-r--r--include/llvm/Support/ELFRelocs/PowerPC.def61
-rw-r--r--include/llvm/Support/ELFRelocs/PowerPC64.def88
-rw-r--r--include/llvm/Support/ELFRelocs/Sparc.def89
-rw-r--r--include/llvm/Support/ELFRelocs/SystemZ.def67
-rw-r--r--include/llvm/Support/ELFRelocs/i386.def47
-rw-r--r--include/llvm/Support/ELFRelocs/x86_64.def44
-rw-r--r--include/llvm/Support/EndianStream.h25
-rw-r--r--include/llvm/Support/ErrorOr.h2
-rw-r--r--include/llvm/Support/FileOutputBuffer.h6
-rw-r--r--include/llvm/Support/FileSystem.h48
-rw-r--r--include/llvm/Support/Format.h190
-rw-r--r--include/llvm/Support/GCOV.h147
-rw-r--r--include/llvm/Support/GenericDomTree.h322
-rw-r--r--include/llvm/Support/GenericDomTreeConstruction.h20
-rw-r--r--include/llvm/Support/LockFileManager.h8
-rw-r--r--include/llvm/Support/MachO.h351
-rw-r--r--include/llvm/Support/MathExtras.h332
-rw-r--r--include/llvm/Support/MemoryBuffer.h4
-rw-r--r--include/llvm/Support/Mutex.h4
-rw-r--r--include/llvm/Support/MutexGuard.h4
-rw-r--r--include/llvm/Support/OnDiskHashTable.h2
-rw-r--r--include/llvm/Support/PrettyStackTrace.h4
-rw-r--r--include/llvm/Support/Process.h102
-rw-r--r--include/llvm/Support/RWMutex.h4
-rw-r--r--include/llvm/Support/RandomNumberGenerator.h41
-rw-r--r--include/llvm/Support/Regex.h2
-rw-r--r--include/llvm/Support/Registry.h9
-rw-r--r--include/llvm/Support/ScaledNumber.h1
-rw-r--r--include/llvm/Support/Signals.h3
-rw-r--r--include/llvm/Support/SourceMgr.h4
-rw-r--r--include/llvm/Support/SpecialCaseList.h30
-rw-r--r--include/llvm/Support/StreamingMemoryObject.h13
-rw-r--r--include/llvm/Support/StringPool.h4
-rw-r--r--include/llvm/Support/SwapByteOrder.h20
-rw-r--r--include/llvm/Support/TargetRegistry.h71
-rw-r--r--include/llvm/Support/ThreadLocal.h2
-rw-r--r--include/llvm/Support/Threading.h3
-rw-r--r--include/llvm/Support/Timer.h6
-rw-r--r--include/llvm/Support/UniqueLock.h4
-rw-r--r--include/llvm/Support/Watchdog.h4
-rw-r--r--include/llvm/Support/YAMLTraits.h17
-rw-r--r--include/llvm/Support/raw_ostream.h4
-rw-r--r--include/llvm/Support/type_traits.h10
-rw-r--r--include/llvm/TableGen/Record.h80
-rw-r--r--include/llvm/Target/Target.td55
-rw-r--r--include/llvm/Target/TargetCallingConv.h11
-rw-r--r--include/llvm/Target/TargetFrameLowering.h19
-rw-r--r--include/llvm/Target/TargetInstrInfo.h17
-rw-r--r--include/llvm/Target/TargetIntrinsicInfo.h4
-rw-r--r--include/llvm/Target/TargetLowering.h312
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h33
-rw-r--r--include/llvm/Target/TargetMachine.h64
-rw-r--r--include/llvm/Target/TargetOpcodes.h13
-rw-r--r--include/llvm/Target/TargetOptions.h12
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h32
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td27
-rw-r--r--include/llvm/Target/TargetSelectionDAGInfo.h5
-rw-r--r--include/llvm/Target/TargetSubtargetInfo.h10
-rw-r--r--include/llvm/Transforms/IPO.h4
-rw-r--r--include/llvm/Transforms/IPO/LowerBitSets.h153
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h21
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombine.h46
-rw-r--r--include/llvm/Transforms/InstCombine/InstCombineWorklist.h116
-rw-r--r--include/llvm/Transforms/Instrumentation.h56
-rw-r--r--include/llvm/Transforms/Scalar.h37
-rw-r--r--include/llvm/Transforms/Scalar/EarlyCSE.h39
-rw-r--r--include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h40
-rw-r--r--include/llvm/Transforms/Scalar/SimplifyCFG.h46
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h158
-rw-r--r--include/llvm/Transforms/Utils/BuildLibCalls.h14
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h67
-rw-r--r--include/llvm/Transforms/Utils/Local.h23
-rw-r--r--include/llvm/Transforms/Utils/LoopUtils.h69
-rw-r--r--include/llvm/Transforms/Utils/PromoteMemToReg.h4
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h4
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h70
-rw-r--r--include/llvm/Transforms/Utils/SymbolRewriter.h4
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h9
-rw-r--r--include/llvm/Transforms/Utils/ValueMapper.h21
-rw-r--r--include/llvm/Transforms/Utils/VectorUtils.h6
-rw-r--r--include/llvm/module.modulemap76
439 files changed, 22711 insertions, 7621 deletions
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<unsigned int>(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<T> &Vec)
: Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
Length(Vec.size()) {}
-#endif
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. 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<bool AddBits, bool InvertMask>
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<typename KeyT, typename ValueT,
- typename KeyInfoT = DenseMapInfo<KeyT>,
- 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 <typename KeyT, typename ValueT>
+struct DenseMapPair : public std::pair<KeyT, ValueT> {
+ KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
+ const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
+ ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
+ const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
+};
+}
+
+template <
+ typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
class DenseMapIterator;
-template<typename DerivedT,
- typename KeyT, typename ValueT, typename KeyInfoT>
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
class DenseMapBase {
-protected:
- typedef std::pair<KeyT, ValueT> BucketT;
-
public:
typedef unsigned size_type;
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef BucketT value_type;
- typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator;
- typedef DenseMapIterator<KeyT, ValueT,
- KeyInfoT, true> const_iterator;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>
+ 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 <typename OtherBaseT>
- void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) {
+ void copyFrom(
+ const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &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<typename KeyT, typename ValueT,
- typename KeyInfoT = DenseMapInfo<KeyT> >
-class DenseMap
- : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>,
- KeyT, ValueT, KeyInfoT> {
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
+ KeyT, ValueT, KeyInfoT, BucketT> {
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT;
- typedef typename BaseT::BucketT BucketT;
- friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>;
+ typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+ friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
BucketT *Buckets;
unsigned NumEntries;
@@ -677,17 +690,17 @@ private:
}
};
-template<typename KeyT, typename ValueT,
- unsigned InlineBuckets = 4,
- typename KeyInfoT = DenseMapInfo<KeyT> >
+template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
class SmallDenseMap
- : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>,
- KeyT, ValueT, KeyInfoT> {
+ : public DenseMapBase<
+ SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
+ ValueT, KeyInfoT, BucketT> {
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT;
- typedef typename BaseT::BucketT BucketT;
- friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>;
+ typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
+ friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
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<typename KeyT, typename ValueT,
- typename KeyInfoT, bool IsConst>
+template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
+ bool IsConst>
class DenseMapIterator {
- typedef std::pair<KeyT, ValueT> Bucket;
- typedef DenseMapIterator<KeyT, ValueT,
- KeyInfoT, true> ConstIterator;
- friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>;
+ typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
+ friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+
public:
typedef ptrdiff_t difference_type;
typedef typename std::conditional<IsConst, const Bucket, Bucket>::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<KeyT, ValueT,
- KeyInfoT, false>& I)
- : Ptr(I.Ptr), End(I.End) {}
+ DenseMapIterator(
+ const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &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 <typename KeyT> 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<typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT> >
class DenseSet {
- typedef DenseMap<ValueT, char, ValueInfoT> MapTy;
+ typedef DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
+ detail::DenseSetPair<ValueT>> 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<iterator, bool> 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 <set>
#include <vector>
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 <cassert>
+#include <cstddef>
#include <set>
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 T, class VectorIteratorT>
-class FoldingSetVectorIterator {
- // Provide a typedef to workaround the lack of correct injected class name
- // support in older GCCs.
- typedef FoldingSetVectorIterator<T, VectorIteratorT> 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<T, typename VectorT::iterator> iterator;
+ typedef pointee_iterator<typename VectorT::iterator> iterator;
iterator begin() { return Vector.begin(); }
iterator end() { return Vector.end(); }
- typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator>
- const_iterator;
+ typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
const_iterator begin() const { return Vector.begin(); }
const_iterator end() const { return Vector.end(); }
@@ -735,31 +695,9 @@ template <typename T>
class FoldingSetNodeWrapper : public FoldingSetNode {
T data;
public:
- explicit FoldingSetNodeWrapper(const T &x) : data(x) {}
- virtual ~FoldingSetNodeWrapper() {}
-
- template<typename A1>
- explicit FoldingSetNodeWrapper(const A1 &a1)
- : data(a1) {}
-
- template <typename A1, typename A2>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2)
- : data(a1,a2) {}
-
- template <typename A1, typename A2, typename A3>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3)
- : data(a1,a2,a3) {}
-
- template <typename A1, typename A2, typename A3, typename A4>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
- const A4 &a4)
- : data(a1,a2,a3,a4) {}
-
- template <typename A1, typename A2, typename A3, typename A4, typename A5>
- explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
- const A4 &a4, const A5 &a5)
- : data(a1,a2,a3,a4,a5) {}
-
+ template <typename... Ts>
+ explicit FoldingSetNodeWrapper(Ts &&... Args)
+ : data(std::forward<Ts>(Args)...) {}
void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::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 <iterator>
#include <utility>
-// 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 <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
- 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 <typename T1, typename T2, typename T3, typename T4, typename T5>
- 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 <typename T1, typename T2, typename T3, typename T4>
- 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 <typename T1, typename T2, typename T3>
- 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 <typename T1, typename T2>
- 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 <typename T1>
- 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 <typename ...Ts> 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 <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-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 <typename T1, typename T2, typename T3, typename T4, typename T5>
-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 <typename T1, typename T2, typename T3, typename T4>
-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 <typename T1, typename T2, typename T3>
-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 <typename T1, typename T2>
-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 <typename T1>
-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<T>;
- 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 <typename NodeT>
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 <typename T> struct IntrusiveRefCntPtrInfo {
static void retain(T *obj) { obj->Retain(); }
static void release(T *obj) { obj->Release(); }
@@ -114,7 +114,7 @@ public:
delete static_cast<const Derived*>(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 <vector>
namespace llvm {
@@ -181,6 +182,14 @@ void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
Vector.erase(O, Vector.end());
}
+/// \brief A MapVector that performs no allocations if smaller than a certain
+/// size.
+template <typename KeyT, typename ValueT, unsigned N>
+struct SmallMapVector
+ : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>,
+ SmallVector<std::pair<KeyT, ValueT>, 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<T>
/// 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<typename ...ArgTypes>
void emplace(ArgTypes &&...Args) {
@@ -80,51 +78,6 @@ public:
new (storage.buffer) T(std::forward<ArgTypes>(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<typename T1>
- void emplace(T1 &&A1) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2>
- void emplace(T1 &&A1, T2 &&A2) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2, typename T3>
- void emplace(T1 &&A1, T2 &&A2, T3 &&A3) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
- std::forward<T3>(A3));
- }
-
- /// Create a new object by constructing it in place with the given arguments.
- template<typename T1, typename T2, typename T3, typename T4>
- void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
- reset();
- hasVal = true;
- new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
- std::forward<T3>(A3), std::forward<T4>(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 <typename PT1, typename PT2>
class PointerUnion {
public:
- typedef PointerIntPair<void*, 1, bool,
+ typedef PointerIntPair<void*, 1, bool,
PointerUnionUIntTraits<PT1,PT2> > ValTy;
private:
ValTy Val;
@@ -96,14 +96,14 @@ namespace llvm {
public:
PointerUnion() {}
-
+
PointerUnion(PT1 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
}
PointerUnion(PT2 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT2>::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<PT1>::getFromVoidPointer(Val.getPointer());
}
- LLVM_EXPLICIT operator bool() const { return !isNull(); }
+ explicit operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
@@ -123,7 +123,7 @@ namespace llvm {
int TyNo = Ty::Num;
return static_cast<int>(Val.getInt()) == TyNo;
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -131,7 +131,7 @@ namespace llvm {
assert(is<T>() && "Invalid accessor called");
return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -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<typename PT1, typename PT2>
+ static bool operator<(PointerUnion<PT1, PT2> lhs,
+ PointerUnion<PT1, PT2> rhs) {
+ return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+ }
+
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits)-1.
template<typename PT1, typename PT2>
@@ -208,16 +214,16 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
::NumLowBitsAvailable
};
};
-
-
+
+
/// PointerUnion3 - This is a pointer union of three pointer types. See
/// documentation for PointerUnion for usage.
template <typename PT1, typename PT2, typename PT3>
@@ -233,7 +239,7 @@ namespace llvm {
IsInnerUnion(ValTy val) : Val(val) { }
template<typename T>
int is() const {
- return Val.template is<InnerUnion>() &&
+ return Val.template is<InnerUnion>() &&
Val.template get<InnerUnion>().template is<T>();
}
template<typename T>
@@ -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<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@@ -283,7 +289,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template is<T>();
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -296,7 +302,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template get<T>();
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -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<typename PT1, typename PT2, typename PT3>
@@ -347,10 +353,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::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<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@@ -395,10 +401,10 @@ namespace llvm {
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
>::Return Ty;
- return Val.template is<Ty>() &&
+ return Val.template is<Ty>() &&
Val.template get<Ty>().template is<T>();
}
-
+
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@@ -411,7 +417,7 @@ namespace llvm {
>::Return Ty;
return Val.template get<Ty>().template get<T>();
}
-
+
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@@ -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<typename PT1, typename PT2, typename PT3, typename PT4>
@@ -466,10 +472,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
}
-
+
// The number of bits available are the min of the two pointer types.
enum {
- NumLowBitsAvailable =
+ NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::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 <cassert>
#include <cstddef> // for std::size_t
#include <cstdlib> // for qsort
#include <functional>
@@ -63,8 +64,6 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> {
/// a function_ref.
template<typename Fn> class function_ref;
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
template<typename Ret, typename ...Params>
class function_ref<Ret(Params...)> {
Ret (*callback)(intptr_t callable, Params ...params);
@@ -89,112 +88,6 @@ public:
}
};
-#else
-
-template<typename Ret>
-class function_ref<Ret()> {
- Ret (*callback)(intptr_t callable);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable) {
- return (*reinterpret_cast<Callable*>(callable))();
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()() const { return callback(callable); }
-};
-
-template<typename Ret, typename Param1>
-class function_ref<Ret(Param1)> {
- Ret (*callback)(intptr_t callable, Param1 param1);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1) {
- return callback(callable, std::forward<Param1>(param1));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2>
-class function_ref<Ret(Param1, Param2)> {
- Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2, typename Param3>
-class function_ref<Ret(Param1, Param2, Param3)> {
- Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3);
- intptr_t callable;
-
- template<typename Callable>
- static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2,
- Param3 param3) {
- return (*reinterpret_cast<Callable*>(callable))(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable,
- typename std::enable_if<
- !std::is_same<typename std::remove_reference<Callable>::type,
- function_ref>::value>::type * = nullptr)
- : callback(callback_fn<typename std::remove_reference<Callable>::type>),
- callable(reinterpret_cast<intptr_t>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(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 <class T, T... I> 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 <size_t... I>
+struct index_sequence : integer_sequence<std::size_t, I...> {};
+
+template <std::size_t N, std::size_t... I>
+struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
+template <std::size_t... I>
+struct build_index_impl<0, I...> : index_sequence<I...> {};
+
+/// \brief Creates a compile-time integer sequence for a parameter pack.
+template <class... Ts>
+struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
+
//===----------------------------------------------------------------------===//
// Extra additions for arrays
//===----------------------------------------------------------------------===//
@@ -392,8 +307,6 @@ void DeleteContainerSeconds(Container &C) {
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
-#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 <class T, class... Args>
typename std::enable_if<std::extent<T>::value != 0>::type
-make_unique(Args &&...) LLVM_DELETED_FUNCTION;
-
-#else
-
-template <class T>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique() {
- return std::unique_ptr<T>(new T());
-}
-
-template <class T, class Arg1>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1) {
- return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1)));
-}
-
-template <class T, class Arg1, class Arg2>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) {
- return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1),
- std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
-make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
- Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) {
- return std::unique_ptr<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8, class Arg9>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::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<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
- std::forward<Arg9>(arg9)));
-}
-
-template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
- class Arg6, class Arg7, class Arg8, class Arg9, class Arg10>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::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<T>(
- new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
- std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
- std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
- std::forward<Arg9>(arg9), std::forward<Arg10>(arg10)));
-}
-
-template <class T>
-typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0,
- std::unique_ptr<T>>::type
-make_unique(size_t n) {
- return std::unique_ptr<T>(new typename std::remove_extent<T>::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<void> in its absence.
+struct less {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) < std::forward<B>(b);
+ }
+};
+
+/// A functor like C++14's std::equal<void> in its absence.
+struct equal {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) == std::forward<B>(b);
+ }
+};
+
+/// Binary functor that adapts to any other binary functor after dereferencing
+/// operands.
+template <typename T> 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 <typename A, typename B>
+ 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<K, V> *LastValInScope;
- void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
- ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
+ void operator=(ScopedHashTableScope&) = delete;
+ ScopedHashTableScope(ScopedHashTableScope&) = delete;
public:
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &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<unsigned>(
+ std::numeric_limits<uintptr_t>::digits) &&
+ "undefined behavior");
setSmallBits(getSmallBits() | (uintptr_t(1) << Idx));
+ }
else
getPointer()->set(Idx);
return *this;
@@ -556,7 +551,6 @@ public:
private:
template<bool AddBits, bool InvertMask>
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 <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> 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<PtrType> iterator;
typedef SmallPtrSetIterator<PtrType> 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<iterator, bool> 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<typename T1, typename T2>
- static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
+ template <typename T1, typename T2>
+ static void uninitialized_copy(
+ T1 *I, T1 *E, T2 *Dest,
+ typename std::enable_if<std::is_same<typename std::remove_const<T1>::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 <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::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<unsigned>(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<unsigned>(this->size() + NumToInsert));
+ reserve(this->size() + NumToInsert);
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
@@ -632,6 +633,13 @@ public:
return I;
}
+ template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
+ if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
+ this->grow();
+ ::new ((void *)this->end()) T(std::forward<ArgTypes>(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<T>::swap(SmallVectorImpl<T> &RHS) {
// Swap the shared elements.
size_t NumShared = this->size();
if (NumShared > RHS.size()) NumShared = RHS.size();
- for (unsigned i = 0; i != static_cast<unsigned>(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<T>(N) {
}
- explicit SmallVector(unsigned Size, const T &Value = T())
+ explicit SmallVector(size_t Size, const T &Value = T())
: SmallVectorImpl<T>(N) {
this->assign(Size, Value);
}
@@ -876,6 +884,17 @@ public:
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
+
+ SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
+ if (!RHS.empty())
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ }
+
+ const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ return *this;
+ }
+
};
template<typename T, unsigned N>
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<typename ValueTy>
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<char*>(&V) -
- (reinterpret_cast<char*>(&EPtr->second) -
- reinterpret_cast<char*>(EPtr));
- return *reinterpret_cast<StringMapEntry*>(Ptr);
- }
- static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
- return GetStringMapEntryFromValue(const_cast<ValueTy&>(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<const unsigned char *>(begin());
+ }
+ const unsigned char *bytes_end() const {
+ return reinterpret_cast<const unsigned char *>(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<EltTy, 4> VecTy;
typedef typename VecTy::value_type value_type;
+ typedef llvm::PointerUnion<EltTy, VecTy *> PtrUnion;
- llvm::PointerUnion<EltTy, VecTy*> Val;
+private:
+ PtrUnion Val;
+public:
TinyPtrVector() {}
~TinyPtrVector() {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
@@ -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<EltTy> Elts)
+ : Val(Elts.size() == 1 ? PtrUnion(Elts[0])
+ : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
+
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
if (Val.isNull())
@@ -105,6 +116,15 @@ public:
return *Val.template get<VecTy*>();
}
+ // implicit conversion operator to MutableArrayRef.
+ operator MutableArrayRef<EltTy>() {
+ if (Val.isNull())
+ return None;
+ if (Val.template is<EltTy>())
+ return *Val.getAddrOfPtr1();
+ return *Val.template get<VecTy*>();
+ }
+
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<typename T>
-void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
+void operator-(int, ilist_iterator<T>) = delete;
template<typename T>
-void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
+void operator-(ilist_iterator<T>,int) = delete;
template<typename T>
-void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
+void operator+(int, ilist_iterator<T>) = delete;
template<typename T>
-void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
+void operator+(ilist_iterator<T>,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 <iterator>
#include <cstddef>
+#include <iterator>
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 <memory>
+
+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 <typename IRUnitT> 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<WeakVH, 4> 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<filter_iterator<...>>
+ /// when we can write that to filter out the null values. Then caller code
+ /// will become simpler.
+ MutableArrayRef<WeakVH> 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<Function> *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<Value *> DMI;
+
+ FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr)
+ : CallbackVH(V), ACT(ACT) {}
+ };
+
+ friend FunctionCallbackVH;
+
+ typedef DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>,
+ 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 <memory>
-
-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<Value *> 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<Instruction *> 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<CallInst*>(V);
-
- return cast<CallInst>(V);
- }
-
- CallInst *operator->() const { return cast<CallInst>(getValPtr()); }
- CallInst &operator*() const { return *cast<CallInst>(getValPtr()); }
- };
-
- friend FunctionCallbackVH;
- friend CallCallbackVH;
-
- // FIXME: SmallSet might be better here, but it currently has no iterators.
- typedef DenseSet<CallCallbackVH, CallCallbackVH::DMI> CallHandleSet;
- typedef DenseMap<FunctionCallbackVH, std::unique_ptr<CallHandleSet>,
- 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_iterator> 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 <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
- Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
- }
-
- static StringRef name() { return "CGSCCPassManager"; }
-
-private:
- // Pull in the concept type and model template specialized for SCCs.
- typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager>
- CGSCCPassConcept;
- template <typename PassT>
- struct CGSCCPassModel
- : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> {
- CGSCCPassModel(PassT Pass)
- : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
-
- CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
- CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
-
- std::vector<std::unique_ptr<CGSCCPassConcept>> 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<CGSCCAnalysisManager,
- LazyCallGraph::SCC *>;
- typedef detail::AnalysisManagerBase<CGSCCAnalysisManager,
- LazyCallGraph::SCC *> 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<BaseT &>(Arg))),
- CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {}
- CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) {
- BaseT::operator=(std::move(static_cast<BaseT &>(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<LazyCallGraph::SCC> 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<void *, std::unique_ptr<detail::AnalysisResultConcept<
- LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT;
-
- /// \brief Map type from function pointer to our custom list type.
- typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT>
- 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<std::pair<void *, LazyCallGraph::SCC *>,
- 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<LazyCallGraph::SCC> 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<FunctionAnalysisManagerCGSCCProxy>(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<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(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<const Value*> &EphValues);
+ static void collectEphemeralValues(const Loop *L, AssumptionCache *AC,
+ SmallPtrSetImpl<const Value *> &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<const Value*> &EphValues);
+ static void collectEphemeralValues(const Function *L, AssumptionCache *AC,
+ SmallPtrSetImpl<const Value *> &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<Type *> 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<Type *> &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 <climits>
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<typename T>
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<Value *> 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 <vector>
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 <iterator>
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 <typename A> 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<TrackingVH<Value>, 2> Pointers;
+ /// Holds the pointer value at the beginning of the loop.
+ SmallVector<const SCEV*, 2> Starts;
+ /// Holds the pointer value at the end of the loop.
+ SmallVector<const SCEV*, 2> Ends;
+ /// Holds the information if this pointer is used for writing to memory.
+ SmallVector<bool, 2> IsWritePtr;
+ /// Holds the id of the set of pointers that could be dependent because of a
+ /// shared underlying object.
+ SmallVector<unsigned, 2> DependencySetId;
+ /// Holds the id of the disjoint alias set to which this pointer belongs.
+ SmallVector<unsigned, 2> 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<Instruction *, Instruction *>
+ addRuntimeCheck(Instruction *Loc) const;
+
+ /// \brief The diagnostics report generated for the analysis. E.g. why we
+ /// couldn't analyze the loop.
+ const Optional<LoopAccessReport> &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<LoopAccessReport> 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<Loop *, std::unique_ptr<LoopAccessInfo>> 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 <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
template<typename T>
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
@@ -74,9 +79,9 @@ class LoopBase {
SmallPtrSet<const BlockT*, 8> DenseBlockSet;
- LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
+ LoopBase(const LoopBase<BlockT, LoopT> &) = delete;
const LoopBase<BlockT, LoopT>&
- operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
+ operator=(const LoopBase<BlockT, LoopT> &) = delete;
public:
/// Loop ctor - This creates an empty loop.
LoopBase() : ParentLoop(nullptr) {}
@@ -496,18 +501,33 @@ class LoopInfoBase {
friend class LoopBase<BlockT, LoopT>;
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<LoopT *>::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<LoopT *>::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<BlockT *, LoopT *>::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<BlockT> &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<BasicBlock, Loop>;
#endif
-class LoopInfo : public FunctionPass {
- LoopInfoBase<BasicBlock, Loop> LI;
+class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
+ typedef LoopInfoBase<BasicBlock, Loop> BaseT;
+
friend class LoopBase<BasicBlock, Loop>;
- 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<BasicBlock, Loop>& getBase() { return LI; }
+ LoopInfo() {}
- /// iterator/begin/end - The interface to the top-level loops in the current
- /// function.
- ///
- typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
- typedef LoopInfoBase<BasicBlock, Loop>::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<BaseT &>(Arg))) {}
+ LoopInfo &operator=(LoopInfo &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<const Loop*> {
typedef const Loop NodeType;
@@ -776,6 +719,65 @@ template <> struct GraphTraits<Loop*> {
}
};
+/// \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<Function> *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<Function> *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<BlockT, LoopT>::print(raw_ostream &OS) const {
#endif
}
+template<class BlockT, class LoopT>
+void LoopInfoBase<BlockT, LoopT>::verify() const {
+ DenseSet<const LoopT*> 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<PredIteratorCache> 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<NonLocalDepResult> &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<NonLocalDepResult> &Result,
DenseMap<BasicBlock*, Value*> &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<Instruction*, 4> 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<Instruction>(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<Tr> {
typedef typename InvBlockTraits::ChildIteratorType PredIterTy;
friend class RegionInfoBase<Tr>;
- 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 <NW> 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 <NW> 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 <NW>. <NW> 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<const SCEV *,
- SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions;
+ SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
+ LoopDispositions;
/// computeLoopDisposition - Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
/// BlockDispositions - Memoized computeBlockDisposition results.
- DenseMap<const SCEV *,
- SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions;
+ DenseMap<
+ const SCEV *,
+ SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 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<BasicBlock*,BasicBlock*> Edge;
std::set<Edge> 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/Target/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
index 249849b..5c6f364 100644
--- a/include/llvm/Target/TargetLibraryInfo.h
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -1,4 +1,4 @@
-//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===//
+//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H
-#define LLVM_TARGET_TARGETLIBRARYINFO_H
+#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
@@ -25,7 +29,7 @@
// END ANDROID-SPECIFIC
namespace llvm {
- class Triple;
+class PreservedAnalyses;
namespace LibFunc {
enum Func {
@@ -703,11 +707,15 @@ namespace llvm {
};
}
-/// TargetLibraryInfo - This immutable pass captures information about what
-/// library functions are available for the current target, and allows a
-/// frontend to disable optimizations through -fno-builtin etc.
-class TargetLibraryInfo : public ImmutablePass {
- virtual void anchor();
+/// \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<unsigned, std::string> CustomNames;
static const char* StandardNames[LibFunc::NumLibFuncs];
@@ -726,25 +734,92 @@ class TargetLibraryInfo : public ImmutablePass {
}
public:
- static char ID;
- TargetLibraryInfo();
- TargetLibraryInfo(const Triple &T);
- explicit TargetLibraryInfo(const TargetLibraryInfo &TLI);
+ TargetLibraryInfoImpl();
+ explicit TargetLibraryInfoImpl(const Triple &T);
- /// getLibFunc - Search for a particular function name. If it is one of the
- /// known library functions, return true and set F to the corresponding value.
+ // 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;
- /// has - This function is used by optimizations that want to match on or form
- /// a given library function.
+ /// \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 getState(F) != Unavailable;
+ return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
- /// hasOptimizedCodeGen - Return true if the function is both available as
- /// a builtin and a candidate for optimized code generation.
+ /// \brief Tests if the function is both available and a candidate for
+ /// optimized code generation.
bool hasOptimizedCodeGen(LibFunc::Func F) const {
- if (getState(F) == Unavailable)
+ if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable)
return false;
switch (F) {
default: break;
@@ -774,38 +849,85 @@ public:
}
StringRef getName(LibFunc::Func F) const {
- AvailabilityState State = getState(F);
- if (State == Unavailable)
+ auto State = Impl->getState(F);
+ if (State == TargetLibraryInfoImpl::Unavailable)
return StringRef();
- if (State == StandardName)
- return StandardNames[F];
- assert(State == CustomName);
- return CustomNames.find(F)->second;
+ if (State == TargetLibraryInfoImpl::StandardName)
+ return Impl->StandardNames[F];
+ assert(State == TargetLibraryInfoImpl::CustomName);
+ return Impl->CustomNames.find(F)->second;
}
- /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to
- /// ban use of specific library functions.
- void setUnavailable(LibFunc::Func F) {
- setState(F, Unavailable);
- }
+ /// \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; }
+};
- void setAvailable(LibFunc::Func F) {
- setState(F, StandardName);
- }
+/// \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;
- 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 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;
}
- /// disableAllFunctions - This disables all builtins, which is used for
- /// options like -fno-builtin.
- void disableAllFunctions();
+ 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<TargetLibraryInfoImpl> PresetInfoImpl;
+
+ StringMap<std::unique_ptr<TargetLibraryInfoImpl>> 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
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 <typename T> 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<const Value *> Operands) const;
+ unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> 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<const Value *> Arguments) const;
+ unsigned getCallCost(const Function *F,
+ ArrayRef<const Value *> 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<Type *> ParamTys) const;
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> 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<const Value *> Arguments) const;
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> 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<Type *> Tys) const;
+ unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
+ ArrayRef<Type *> 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<Type*> Tys) const;
+ unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> 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 <typename T> class Model;
+
+ std::unique_ptr<Concept> 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<const Value *> 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<const Value *> Arguments) = 0;
+ virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) = 0;
+ virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> 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<Type *> Tys) = 0;
+ virtual unsigned getNumberOfParts(Type *Tp) = 0;
+ virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0;
+ virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0;
+ virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst,
+ MemIntrinsicInfo &Info) = 0;
+ virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) = 0;
+};
+
+template <typename T>
+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<const Value *> 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<const Value *> Arguments) override {
+ return Impl.getCallCost(F, Arguments);
+ }
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> ParamTys) override {
+ return Impl.getIntrinsicCost(IID, RetTy, ParamTys);
+ }
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> 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<Type *> 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<Type *> 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 <typename T>
+TargetTransformInfo::TargetTransformInfo(T Impl)
+ : TTIImpl(new Model<T>(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<Result(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<Result(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<TargetTransformInfo> 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<const Value *> 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<Constant>(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<Type *> 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<Type *> 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<Type *> 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 <typename T>
+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<const BaseT &>(Arg)) {}
+ TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ TargetTransformInfoImplCRTPBase &
+ operator=(const TargetTransformInfoImplCRTPBase &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ return *this;
+ }
+ TargetTransformInfoImplCRTPBase &
+ operator=(TargetTransformInfoImplCRTPBase &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end());
+ return static_cast<T *>(this)
+ ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys);
+ }
+
+ if (!static_cast<T *>(this)->isLoweredToCall(F))
+ return TTI::TCC_Basic; // Give a basic cost if it will be lowered
+ // directly.
+
+ return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs);
+ }
+
+ unsigned getCallCost(const Function *F, ArrayRef<const Value *> 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<T *>(this)->getCallCost(F, Arguments.size());
+ }
+
+ using BaseT::getIntrinsicCost;
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> 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<Type *, 8> ParamTys;
+ ParamTys.reserve(Arguments.size());
+ for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx)
+ ParamTys.push_back(Arguments[Idx]->getType());
+ return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys);
+ }
+
+ unsigned getUserCost(const User *U) {
+ if (isa<PHINode>(U))
+ return TTI::TCC_Free; // Model all PHI nodes as free.
+
+ if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
+ SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end());
+ return static_cast<T *>(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<T *>(this)
+ ->getCallCost(cast<FunctionType>(FTy), CS.arg_size());
+ }
+
+ SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end());
+ return static_cast<T *>(this)->getCallCost(F, Arguments);
+ }
+
+ if (const CastInst *CI = dyn_cast<CastInst>(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<CmpInst>(CI->getOperand(0)))
+ return TTI::TCC_Free;
+ }
+
+ return static_cast<T *>(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<MemoryObject> 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 <memory>
@@ -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<Module *> getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&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<Module *>
+ getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+ LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr);
+
+ /// Read the header of the specified stream and prepare for lazy
+ /// deserialization and streaming of function bodies.
+ ErrorOr<std::unique_ptr<Module>> 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<Module *> parseBitcodeFile(MemoryBufferRef Buffer,
- LLVMContext &Context);
+ ErrorOr<Module *>
+ 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<int>(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<const GlobalVariable *, unsigned> GOTEquivUsePair;
+ DenseMap<const MCSymbol *, GOTEquivUsePair> 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<MCStreamer> 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<unsigned> 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 <typename T>
+class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
+private:
+ typedef TargetTransformInfoImplCRTPBase<T> 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<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ if (Extract)
+ Cost += static_cast<T *>(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<T *>(this)
+ ->getVectorInstrCost(Instruction::InsertElement, Ty, i);
+ Cost += static_cast<T *>(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<const T *>(this)->getST();
+ }
+
+ /// \brief Local query method delegates up to T which *must* implement this!
+ const TargetLoweringBase *getTLI() const {
+ return static_cast<const T *>(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<const BaseT &>(Arg)) {}
+ BasicTTIImplBase(BasicTTIImplBase &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
+ BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ return *this;
+ }
+ BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<const Value *> Arguments) {
+ return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
+ }
+
+ unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<Type *> 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<CallInst>(J) || isa<InvokeInst>(J)) {
+ ImmutableCallSite CS(J);
+ if (const Function *F = CS.getCalledFunction()) {
+ if (!static_cast<T *>(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<unsigned, MVT> 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<T *>(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<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src);
+ std::pair<unsigned, MVT> 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<T *>(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<unsigned, MVT> 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<T *>(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<unsigned, MVT> 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<unsigned, MVT> 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<Type *> 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<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0);
+ case Intrinsic::masked_load:
+ return static_cast<T *>(this)
+ ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
+ }
+
+ const TargetLoweringBase *TLI = getTLI();
+ std::pair<unsigned, MVT> 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<T *>(this)
+ ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) +
+ static_cast<T *>(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<T *>(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<unsigned, MVT> 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<T *>(this)->getArithmeticInstrCost(Opcode, Ty);
+ // Assume the pairwise shuffles add a cost.
+ unsigned ShuffleCost =
+ NumReduxLevels * (IsPairwise + 1) *
+ static_cast<T *>(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<BasicTTIImpl> {
+ typedef BasicTTIImplBase<BasicTTIImpl> BaseT;
+ friend class BasicTTIImplBase<BasicTTIImpl>;
+
+ 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<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
+ BasicTTIImpl(BasicTTIImpl &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
+ TLI(std::move(Arg.TLI)) {}
+ BasicTTIImpl &operator=(const BasicTTIImpl &RHS) {
+ BaseT::operator=(static_cast<const BaseT &>(RHS));
+ ST = RHS.ST;
+ TLI = RHS.TLI;
+ return *this;
+ }
+ BasicTTIImpl &operator=(BasicTTIImpl &&RHS) {
+ BaseT::operator=(std::move(static_cast<BaseT &>(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<MCPhysReg> 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<MCPhysReg> 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<uint16_t> 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<MCPhysReg> 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<MCPhysReg> 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<MCPhysReg> &Regs, MVT VT,
+ CCAssignFn Fn);
+
+ /// Compute the set of registers that need to be preserved and forwarded to
+ /// any musttail calls.
+ void analyzeMustTailForwardedRegisters(
+ SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> 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<bool> UniqueSectionNames("unique-section-names",
+ cl::desc("Give unique names to every section"),
+ cl::init(true));
+
cl::opt<llvm::JumpTable::JumpTableType>
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 <vector>
+
+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<DIEAbbrevData, 12> 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<DIEAbbrevData> &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<DIE> because pointer validity is requirent for the
+ // Parent pointer and DIEEntry.
+ // It can't be a list<DIE> 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<std::unique_ptr<DIE>> Children;
+
+ DIE *Parent;
+
+ /// Attribute values.
+ ///
+ SmallVector<DIEValue *, 12> 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<std::unique_ptr<DIE>> &getChildren() const {
+ return Children;
+ }
+ const SmallVectorImpl<DIEValue *> &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<DIE> 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<Value *, 16> OutVals;
SmallVector<ISD::ArgFlagsTy, 16> OutFlags;
SmallVector<unsigned, 16> 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 <string>
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<unsigned, unsigned> 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<unsigned, 50> 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 <memory>
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<GCPoint>::iterator iterator;
+ typedef std::vector<GCRoot>::iterator roots_iterator;
+ typedef std::vector<GCRoot>::const_iterator live_iterator;
+
+private:
+ const Function &F;
+ GCStrategy &S;
+ uint64_t FrameSize;
+ std::vector<GCRoot> Roots;
+ std::vector<GCPoint> 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<GCPoint>::iterator iterator;
- typedef std::vector<GCRoot>::iterator roots_iterator;
- typedef std::vector<GCRoot>::const_iterator live_iterator;
-
- private:
- const Function &F;
- GCStrategy &S;
- uint64_t FrameSize;
- std::vector<GCRoot> Roots;
- std::vector<GCPoint> 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<GCStrategy*> strategy_map_type;
- typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
- typedef DenseMap<const Function*,GCFunctionInfo*> 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<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
+ /// A helper map to speedup lookups into the above list
+ StringMap<GCStrategy*> 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<std::unique_ptr<GCFunctionInfo>> 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<const Function *, GCFunctionInfo *> finfo_map_type;
+ finfo_map_type FInfoMap;
+
+public:
+ typedef SmallVector<std::unique_ptr<GCStrategy>,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<GCMetadataPrinter> 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<GCMetadataPrinter> 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 <string>
namespace llvm {
-
- class GCStrategy;
-
- /// The GC strategy registry uses all the defaults from Registry.
- ///
- typedef Registry<GCStrategy> 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<std::unique_ptr<GCFunctionInfo>> 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<bool> 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<CustomGC> 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<GCStrategy> 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 <utility>
#include <unordered_map>
+#include <utility>
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<const MDNode> Desc; // Debug info descriptor.
- AssertingVH<const MDNode> 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<LexicalScope *, 4> 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 <cassert>
#include <climits>
+#include <set>
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<Segment> 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<typename T>
+ class SingleLinkedListIterator {
+ T *P;
+ public:
+ SingleLinkedListIterator<T>(T *P) : P(P) {}
+ SingleLinkedListIterator<T> &operator++() {
+ P = P->Next;
+ return *this;
+ }
+ SingleLinkedListIterator<T> &operator++(int) {
+ SingleLinkedListIterator res = *this;
+ ++*this;
+ return res;
+ }
+ bool operator!=(const SingleLinkedListIterator<T> &Other) {
+ return P != Other.operator->();
+ }
+ bool operator==(const SingleLinkedListIterator<T> &Other) {
+ return P == Other.operator->();
+ }
+ T &operator*() const {
+ return *P;
+ }
+ T *operator->() const {
+ return P;
+ }
+ };
+
+ typedef SingleLinkedListIterator<SubRange> subrange_iterator;
+ subrange_iterator subrange_begin() {
+ return subrange_iterator(SubRanges);
+ }
+ subrange_iterator subrange_end() {
+ return subrange_iterator(nullptr);
+ }
+
+ typedef SingleLinkedListIterator<const SubRange> 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<subrange_iterator> subranges() {
+ return make_range(subrange_begin(), subrange_end());
+ }
+
+ iterator_range<const_subrange_iterator> 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 <cmath>
#include <iterator>
namespace llvm {
+extern cl::opt<bool> UseSegmentSetForPhysRegs;
+
class AliasAnalysis;
class BitVector;
class BlockFrequency;
@@ -154,16 +157,11 @@ namespace llvm {
bool shrinkToUses(LiveInterval *li,
SmallVectorImpl<MachineInstr*> *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<MachineInstr*> *dead);
+ /// Specialized version of
+ /// shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *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<SlotIndex> 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<SlotIndex> *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<MachineInstr*> *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<unsigned> 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<MachineBasicBlock>::iterator iterator;
typedef DominanceFrontierBase<MachineBasicBlock>::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<typename Ty>
+ static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) {
+ return new (Allocator.Allocate<Ty>()) 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<typename STC> const STC &getSubtarget() const {
+ return *static_cast<const STC *>(STI);
+ }
+
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
@@ -239,7 +255,7 @@ public:
template<typename Ty>
Ty *getInfo() {
if (!MFInfo)
- MFInfo = new (Allocator.Allocate<Ty>()) Ty(*this);
+ MFInfo = Ty::template create<Ty>(Allocator, *this);
return static_cast<Ty*>(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<MachineInstr>;
@@ -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<MachineBasicBlock, MachineLoop> LI;
friend class LoopBase<MachineBasicBlock, MachineLoop>;
- 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<MCSymbol*, 1> BeginLabels; // Labels prior to invoke.
SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke.
+ SmallVector<MCSymbol*, 1> ClauseLabels; // Labels for each clause.
MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
const Function *Personality; // Personality function.
std::vector<int> 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<MDNode> Var;
- TrackingVH<MDNode> 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<VariableDbgInfo, 4> 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 RegistryClass>
class RegisterPassParser : public MachinePassRegistryListener,
public cl::parser<typename RegistryClass::FunctionPassCtor> {
public:
- RegisterPassParser() {}
+ RegisterPassParser(cl::Option &O)
+ : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {}
~RegisterPassParser() { RegistryClass::setListener(nullptr); }
- void initialize(cl::Option &O) {
- cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O);
+ void initialize() {
+ cl::parser<typename RegistryClass::FunctionPassCtor>::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<std::pair<unsigned, unsigned> > 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 <memory>
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_iterator> 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 <typename OtherMatrixT>
- 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 <typename OStream>
- 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 <typename OStream>
- 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 <typename VectorT>
+ 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<PBQP::PBQPNum>::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<MyStrategy>(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<unsigned[]> 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<RegAllocSolverImpl> 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<const SDNode*, SmallVector<SDDbgValue*, 2> > 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<SDNode *> &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<SDValue> 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:
+/// <num call arguments>, <call target>, [call arguments],
+/// <StackMaps::ConstantOp>, <flags>,
+/// <StackMaps::ConstantOp>, <num other args>, [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<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<uint64_t, uint64_t> 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<Module::ModuleFlagEntry> 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 <dirent.h> 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 <sys/types.h> 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 <dirent.h> 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 <malloc.h> 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/DWARF/DIContext.h
index 3aa098d..622aa69 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DWARF/DIContext.h
@@ -21,7 +21,6 @@
#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
-
#include <string>
namespace llvm {
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<AttributeSpec, 8> 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<AttributeSpecVector::const_iterator>
+ 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 <cstdint>
+
+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<std::pair<AtomType, Form>, 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 <vector>
+
+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<DWARFCompileUnit> CUs;
+ std::vector<DWARFUnitSection<DWARFTypeUnit>> TUs;
+ std::unique_ptr<DWARFDebugAbbrev> Abbrev;
+ std::unique_ptr<DWARFDebugLoc> Loc;
+ std::unique_ptr<DWARFDebugAranges> Aranges;
+ std::unique_ptr<DWARFDebugLine> Line;
+ std::unique_ptr<DWARFDebugFrame> DebugFrame;
+
+ DWARFUnitSection<DWARFCompileUnit> DWOCUs;
+ std::vector<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
+ std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
+ std::unique_ptr<DWARFDebugLocDWO> 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<DWARFCompileUnit>::iterator_range cu_iterator_range;
+ typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
+ typedef iterator_range<std::vector<DWARFUnitSection<DWARFTypeUnit>>::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<object::SectionRef, DWARFSection,
+ std::map<object::SectionRef, unsigned>> 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<SmallString<32>, 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 <list>
+#include <map>
+#include <vector>
+
+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<DWARFAbbreviationDeclaration> 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<uint64_t, DWARFAbbreviationDeclarationSet>
+ 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 <vector>
+
+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<Descriptor> DescriptorColl;
+ typedef iterator_range<DescriptorColl::const_iterator> 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 <vector>
+
+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<Range> RangeColl;
+ typedef RangeColl::const_iterator RangeCollIterator;
+
+ std::vector<RangeEndpoint> Endpoints;
+ RangeColl Aranges;
+ DenseSet<uint32_t> 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 <memory>
+#include <vector>
+
+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<std::unique_ptr<FrameEntry>> 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<DWARFDebugInfoEntryMinimal, 4> 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 <map>
+#include <string>
+#include <vector>
+
+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<uint8_t> StandardOpcodeLengths;
+ std::vector<const char*> IncludeDirectories;
+ std::vector<FileNameEntry> 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<uint32_t> &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<Row> RowVector;
+ typedef RowVector::const_iterator RowIter;
+ typedef std::vector<Sequence> 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<uint32_t, LineTable> 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<unsigned char, 4> 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<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> 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<unsigned char, 4> Loc;
+ };
+
+ struct LocationList {
+ unsigned Offset;
+ SmallVector<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> 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 <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// DWARFAddressRangesVector - represents a set of absolute address ranges.
+typedef std::vector<std::pair<uint64_t, uint64_t>> 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<RangeListEntry> 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/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 5bb6d1b..5bb6d1b 100644
--- a/include/llvm/DebugInfo/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
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<uint64_t, std::pair<uint8_t, int64_t> > 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 <vector>
+
+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<typename UnitType>
+class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
+ public DWARFUnitSectionBase {
+
+ struct UnitOffsetComparator {
+ bool operator()(uint32_t LHS,
+ const std::unique_ptr<UnitType> &RHS) const {
+ return LHS < RHS->getNextUnitOffset();
+ }
+ };
+
+ bool Parsed;
+
+public:
+ DWARFUnitSection() : Parsed(false) {}
+ DWARFUnitSection(DWARFUnitSection &&DUS) :
+ SmallVector<std::unique_ptr<UnitType>, 1>(std::move(DUS)), Parsed(DUS.Parsed) {}
+
+ typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
+ typedef typename UnitVector::iterator iterator;
+ typedef llvm::iterator_range<typename UnitVector::iterator> 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<UnitType>(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<DWARFDebugInfoEntryMinimal> DieArray;
+
+ class DWOHolder {
+ object::OwningBinary<object::ObjectFile> DWOFile;
+ std::unique_ptr<DWARFContext> DWOContext;
+ DWARFUnit *DWOU;
+ public:
+ DWOHolder(StringRef DWOPath);
+ DWARFUnit *getUnit() const { return DWOU; }
+ };
+ std::unique_ptr<DWOHolder> 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<DWARFDebugInfoEntryMinimal> &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/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 <memory>
+
+namespace llvm {
+
+template <typename ChildType>
+class ConcreteSymbolEnumerator : public IPDBEnumChildren<ChildType> {
+public:
+ ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator)
+ : Enumerator(std::move(SymbolEnumerator)) {}
+
+ virtual ~ConcreteSymbolEnumerator() {}
+
+ uint32_t getChildCount() const override {
+ return Enumerator->getChildCount();
+ }
+
+ std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override {
+ std::unique_ptr<PDBSymbol> Child = Enumerator->getChildAtIndex(Index);
+ return make_concrete_child(std::move(Child));
+ }
+
+ std::unique_ptr<ChildType> getNext() override {
+ std::unique_ptr<PDBSymbol> Child = Enumerator->getNext();
+ return make_concrete_child(std::move(Child));
+ }
+
+ void reset() override { Enumerator->reset(); }
+
+ ConcreteSymbolEnumerator<ChildType> *clone() const override {
+ std::unique_ptr<IPDBEnumSymbols> WrappedClone(Enumerator->clone());
+ return new ConcreteSymbolEnumerator<ChildType>(std::move(WrappedClone));
+ }
+
+private:
+ std::unique_ptr<ChildType>
+ make_concrete_child(std::unique_ptr<PDBSymbol> Child) const {
+ ChildType *ConcreteChild = dyn_cast_or_null<ChildType>(Child.release());
+ return std::unique_ptr<ChildType>(ConcreteChild);
+ }
+
+ std::unique_ptr<IPDBEnumSymbols> 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<IDiaEnumDebugStreamData> DiaStreamData);
+
+ uint32_t getRecordCount() const override;
+ std::string getName() const override;
+ llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const override;
+ bool getNext(RecordType &Record) override;
+ void reset() override;
+ DIADataStream *clone() const override;
+
+private:
+ CComPtr<IDiaEnumDebugStreamData> 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<IPDBDataStream> {
+public:
+ explicit DIAEnumDebugStreams(CComPtr<IDiaEnumDebugStreams> 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<IDiaEnumDebugStreams> 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<IPDBLineNumber> {
+public:
+ explicit DIAEnumLineNumbers(CComPtr<IDiaEnumLineNumbers> 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<IDiaEnumLineNumbers> 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<IPDBSourceFile> {
+public:
+ explicit DIAEnumSourceFiles(const DIASession &PDBSession,
+ CComPtr<IDiaEnumSourceFiles> 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<IDiaEnumSourceFiles> 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<PDBSymbol> {
+public:
+ explicit DIAEnumSymbols(const DIASession &Session,
+ CComPtr<IDiaEnumSymbols> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+ DIAEnumSymbols *clone() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaEnumSymbols> 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<IDiaLineNumber> 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<IDiaLineNumber> 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<IDiaSymbol> DiaSymbol);
+
+ void dump(raw_ostream &OS, int Indent) const override;
+
+ CComPtr<IDiaSymbol> getDiaSymbol() const { return Symbol; }
+
+ std::unique_ptr<IPDBEnumSymbols>
+ DIARawSymbol::findChildren(PDB_SymType Type) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint32_t RVA) const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByRVA(uint32_t RVA) const override;
+
+ void getDataBytes(llvm::SmallVector<uint8_t, 32> &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<IDiaSymbol> 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<IDiaSession> DiaSession);
+
+ static DIASession *createFromPdb(StringRef Path);
+
+ uint64_t getLoadAddress() const override;
+ void setLoadAddress(uint64_t Address) override;
+ std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
+ std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
+
+ std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override;
+ std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const override;
+ std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t FileId) const override;
+
+ std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
+
+private:
+ CComPtr<IDiaSession> 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<IDiaSourceFile> DiaSourceFile);
+
+ std::string getFileName() const override;
+ uint32_t getUniqueId() const override;
+ std::string getChecksum() const override;
+ PDB_Checksum getChecksumType() const override;
+ std::unique_ptr<IPDBEnumSymbols> getCompilands() const override;
+
+private:
+ const DIASession &Session;
+ CComPtr<IDiaSourceFile> 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 <atlbase.h>
+#include <windows.h>
+
+// DIA headers must come after windows headers.
+#include <cvconst.h>
+#include <dia2.h>
+
+#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<uint8_t, 32> RecordType;
+
+ virtual ~IPDBDataStream();
+
+ virtual uint32_t getRecordCount() const = 0;
+ virtual std::string getName() const = 0;
+ virtual llvm::Optional<RecordType> 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 <memory>
+
+namespace llvm {
+
+template <typename ChildType> class IPDBEnumChildren {
+public:
+ typedef std::unique_ptr<ChildType> ChildTypePtr;
+ typedef IPDBEnumChildren<ChildType> 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 <memory>
+
+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<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint32_t RVA) const = 0;
+ virtual std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByRVA(uint32_t RVA) const = 0;
+
+ virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &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 <memory>
+
+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<PDBSymbolExe> getGlobalScope() const = 0;
+ virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0;
+
+ template <typename T>
+ std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const {
+ auto Symbol(getSymbolById(SymbolId));
+ if (!Symbol)
+ return nullptr;
+
+ T *ConcreteSymbol = dyn_cast<T>(Symbol.get());
+ if (!ConcreteSymbol)
+ return nullptr;
+ Symbol.release();
+ return std::unique_ptr<T>(ConcreteSymbol);
+ }
+
+ virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0;
+ virtual std::unique_ptr<IPDBEnumSourceFiles>
+ getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0;
+ virtual std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t FileId) const = 0;
+
+ virtual std::unique_ptr<IPDBEnumDataStreams> 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 <memory>
+#include <string>
+
+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<IPDBEnumSymbols> 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 <memory>
+
+namespace llvm {
+class StringRef;
+
+std::unique_ptr<IPDBSession> 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 <unordered_map>
+
+namespace llvm {
+typedef std::unordered_map<PDB_SymType, int> 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 <unordered_map>
+
+#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<IPDBRawSymbol> Symbol);
+
+public:
+ static std::unique_ptr<PDBSymbol>
+ create(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> 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 <typename T> std::unique_ptr<T> findOneChild() const {
+ auto Enumerator(findAllChildren<T>());
+ return Enumerator->getNext();
+ }
+
+ template <typename T>
+ std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const {
+ auto BaseIter = RawSymbol->findChildren(T::Tag);
+ return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter));
+ }
+ std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const;
+ std::unique_ptr<IPDBEnumSymbols> findAllChildren() const;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const;
+ std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type,
+ StringRef Name,
+ PDB_NameSearchFlags Flags,
+ uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const;
+
+ const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
+ IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
+
+ const IPDBSession &getSession() const { return Session; }
+
+ std::unique_ptr<IPDBEnumSymbols> getChildStats(TagStats &Stats) const;
+
+protected:
+ const IPDBSession &Session;
+ const std::unique_ptr<IPDBRawSymbol> 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 <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolAnnotation : public PDBSymbol {
+public:
+ PDBSymbolAnnotation(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> 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 <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolBlock : public PDBSymbol {
+public:
+ PDBSymbolBlock(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> 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 <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolCompiland : public PDBSymbol {
+public:
+ PDBSymbolCompiland(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> CustomSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom)
+
+ void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override;
+
+ void getDataBytes(llvm::SmallVector<uint8_t, 32> &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<IPDBRawSymbol> DataSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data)
+
+ std::unique_ptr<PDBSymbol> 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 <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolExe : public PDBSymbol {
+public:
+ PDBSymbolExe(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> 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<IPDBRawSymbol> FuncSymbol);
+
+ void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override;
+
+ std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const;
+ std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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 <string>
+
+namespace llvm {
+
+class raw_ostream;
+
+class PDBSymbolThunk : public PDBSymbol {
+public:
+ PDBSymbolThunk(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> 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<IPDBRawSymbol> ArrayTypeSymbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType)
+
+ std::unique_ptr<PDBSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig)
+
+ std::unique_ptr<PDBSymbol> getReturnType() const;
+ std::unique_ptr<IPDBEnumSymbols> getArguments() const;
+ std::unique_ptr<PDBSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> Symbol);
+
+ DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType)
+
+ std::unique_ptr<PDBSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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<IPDBRawSymbol> 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 <functional>
+#include <stdint.h>
+
+namespace llvm {
+
+class PDBSymDumper;
+class PDBSymbol;
+
+class IPDBDataStream;
+template <class T> class IPDBEnumChildren;
+class IPDBRawSymbol;
+class IPDBSession;
+class IPDBSourceFile;
+
+typedef IPDBEnumChildren<PDBSymbol> IPDBEnumSymbols;
+typedef IPDBEnumChildren<IPDBSourceFile> IPDBEnumSourceFiles;
+typedef IPDBEnumChildren<IPDBDataStream> 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<llvm::PDB_SymType> {
+ typedef llvm::PDB_SymType argument_type;
+ typedef std::size_t result_type;
+
+ result_type operator()(const argument_type &Arg) const {
+ return std::hash<int>()(static_cast<int>(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<Module> M,
- std::string *ErrorStr,
- RTDyldMemoryManager *MCJMM,
- std::unique_ptr<TargetMachine> TM);
+ static ExecutionEngine *(*MCJITCtor)(
+ std::unique_ptr<Module> M,
+ std::string *ErrorStr,
+ std::unique_ptr<RTDyldMemoryManager> MCJMM,
+ std::unique_ptr<TargetMachine> TM);
+
+ static ExecutionEngine *(*OrcMCJITReplacementCtor)(
+ std::string *ErrorStr,
+ std::unique_ptr<RTDyldMemoryManager> OrcJMM,
+ std::unique_ptr<TargetMachine> TM);
+
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@@ -463,6 +470,7 @@ public:
}
protected:
+ ExecutionEngine() : EEState(*this) {}
explicit ExecutionEngine(std::unique_ptr<Module> M);
void emitGlobals();
@@ -492,7 +500,7 @@ private:
EngineKind::Kind WhichEngine;
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
- RTDyldMemoryManager *MCJMM;
+ std::unique_ptr<RTDyldMemoryManager> MCJMM;
TargetOptions Options;
Reloc::Model RelocModel;
CodeModel::Model CMModel;
@@ -500,15 +508,20 @@ private:
std::string MCPU;
SmallVector<std::string, 4> 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<Module> M) : M(std::move(M)) {
- InitEngine();
- }
+ EngineBuilder(std::unique_ptr<Module> 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<RTDyldMemoryManager> 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<MemoryBuffer> 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<MemoryBuffer> 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<char, 4096> 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<ObjectBuffer> Buffer;
-
-public:
- ObjectImage(std::unique_ptr<ObjectBuffer> 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<object::symbol_iterator> symbols() const {
- return iterator_range<object::symbol_iterator>(begin_symbols(),
- end_symbols());
- }
-
- virtual object::section_iterator begin_sections() const = 0;
- virtual object::section_iterator end_sections() const = 0;
- iterator_range<object::section_iterator> sections() const {
- return iterator_range<object::section_iterator>(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<N>,
+ /// 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<char> &&SV)
+ : SV(std::move(SV)), BufferName("<in-memory object>") {
+ init(this->SV.begin(), this->SV.end(), false);
+ }
+
+ /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector
+ /// r-value and StringRef.
+ ObjectMemoryBuffer(SmallVectorImpl<char> &&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<char, 0> 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 <functional>
+
+namespace llvm {
+
+class Function;
+class GlobalVariable;
+class Module;
+
+namespace orc {
+
+/// @brief Functor type for describing how CloneSubModule should mutate a
+/// GlobalVariable.
+typedef std::function<void(GlobalVariable &, const GlobalVariable &,
+ ValueToValueMapTy &)> HandleGlobalVariableFtor;
+
+/// @brief Functor type for describing how CloneSubModule should mutate a
+/// Function.
+typedef std::function<void(Function &, const Function &, ValueToValueMapTy &)>
+ 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 <list>
+
+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 <typename BaseLayerT, typename CompileCallbackMgrT>
+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<BaseLayerModuleSetHandleT> SiblingHandlesList;
+ typedef std::list<SiblingHandlesList> 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<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT;
+
+ struct ModuleSetInfo {
+ // Symbol lookup - just one for the whole module set.
+ std::shared_ptr<CODScopedLookup> Lookup;
+
+ // Logical module handles.
+ std::vector<typename CODScopedLookup::LMHandle> 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<CODScopedLookup> 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<ModuleSetInfo> ModuleSetInfoListT;
+
+public:
+ /// @brief Handle to a set of loaded modules.
+ typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
+
+ // @brief Fallback lookup functor.
+ typedef std::function<uint64_t(const std::string &)> 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 <typename ModuleSetT>
+ 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<CODScopedLookup>(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<std::string,
+ typename CompileCallbackMgrT::CompileCallbackInfo>
+ 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<typename StubInfoMap::iterator> 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<Module> 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<std::unique_ptr<Module>> MSet;
+ MSet.push_back(std::move(M));
+
+ auto DylibLookup = MSI.Lookup;
+ auto MM =
+ createLookasideRTDyldMM<SectionMemoryManager>(
+ [=](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<object::ObjectFile> operator()(Module &M) const {
+ SmallVector<char, 0> 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<MemoryBuffer> ObjBuffer(
+ new ObjectMemoryBuffer(std::move(ObjBufferSV)));
+ ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+ // TODO: Actually report errors helpfully.
+ typedef object::OwningBinary<object::ObjectFile> 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 <memory>
+
+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 <typename BaseLayerT> class IRCompileLayer {
+public:
+ typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)>
+ CompileFtor;
+
+private:
+ typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
+
+ typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;
+ typedef std::vector<std::unique_ptr<MemoryBuffer>> 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 <typename ModuleSetT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ std::unique_ptr<RTDyldMemoryManager> MM) {
+ OwningObjectVec Objects;
+ OwningBufferVec Buffers;
+
+ for (const auto &M : Ms) {
+ std::unique_ptr<object::ObjectFile> Object;
+ std::unique_ptr<MemoryBuffer> 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<object::ObjectFile>
+ tryToLoadFromObjectCache(const Module &M) {
+ std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
+ if (!ObjBuffer)
+ return object::OwningBinary<object::ObjectFile>();
+
+ ErrorOr<std::unique_ptr<object::ObjectFile>> Obj =
+ object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
+ if (!Obj)
+ return object::OwningBinary<object::ObjectFile>();
+
+ return object::OwningBinary<object::ObjectFile>(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 <sstream>
+
+namespace llvm {
+namespace orc {
+
+/// @brief Base class for JITLayer independent aspects of
+/// JITCompileCallbackManager.
+template <typename TargetT>
+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<TargetAddress()> CompileFtorT;
+ typedef std::function<void(TargetAddress)> UpdateFtorT;
+
+ struct CallbackHandler {
+ CompileFtorT Compile;
+ UpdateFtorT Update;
+ };
+
+ TargetAddress ErrorHandlerAddress;
+ unsigned NumTrampolinesPerBlock;
+
+ typedef std::map<TargetAddress, CallbackHandler> TrampolineMapT;
+ TrampolineMapT ActiveTrampolines;
+ std::vector<TargetAddress> AvailableTrampolines;
+};
+
+/// @brief Manage compile callbacks.
+template <typename JITLayerT, typename TargetT>
+class JITCompileCallbackManager :
+ public JITCompileCallbackManagerBase<TargetT> {
+public:
+
+ typedef typename JITCompileCallbackManagerBase<TargetT>::CompileFtorT
+ CompileFtorT;
+ typedef typename JITCompileCallbackManagerBase<TargetT>::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<TargetT>(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<void*>(
+ static_cast<uintptr_t>(FPSym.getAddress()));
+ memcpy(FPAddr, &Addr, sizeof(uintptr_t));
+ };
+ }
+
+private:
+
+ std::vector<std::unique_ptr<Module>>
+ SingletonSet(std::unique_ptr<Module> M) {
+ std::vector<std::unique_ptr<Module>> Ms;
+ Ms.push_back(std::move(M));
+ return Ms;
+ }
+
+ void emitResolverBlock(LLVMContext &Context) {
+ std::unique_ptr<Module> 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<Module> 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<Module*, DenseSet<const GlobalValue*>> ModulePartitionMap;
+
+void partition(Module &M, const ModulePartitionMap &PMap);
+
+/// @brief Struct for trivial "complete" partitioning of a module.
+class FullyPartitionedModule {
+public:
+ std::unique_ptr<Module> GlobalVars;
+ std::unique_ptr<Module> Commons;
+ std::vector<std::unique_ptr<Module>> 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 <cassert>
+#include <functional>
+
+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<TargetAddress()> 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 <list>
+
+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 <typename BaseLayerT> 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 <typename ModuleSetT>
+ static std::unique_ptr<EmissionDeferredSet>
+ create(BaseLayerT &B, ModuleSetT Ms,
+ std::unique_ptr<RTDyldMemoryManager> 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 <typename ModuleSetT>
+ class EmissionDeferredSetImpl : public EmissionDeferredSet {
+ public:
+ EmissionDeferredSetImpl(ModuleSetT Ms,
+ std::unique_ptr<RTDyldMemoryManager> 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<bool> &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<StringMap<bool>>();
+
+ 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<RTDyldMemoryManager> MM;
+ mutable std::unique_ptr<StringMap<bool>> MangledNames;
+ };
+
+ typedef std::list<std::unique_ptr<EmissionDeferredSet>> 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 <typename ModuleSetT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ std::unique_ptr<RTDyldMemoryManager> 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 <typename BaseLayerT>
+template <typename ModuleSetT>
+std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
+LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
+ BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) {
+ return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(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 <memory>
+#include <vector>
+
+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 <typename BaseRTDyldMM, typename ExternalLookupFtor,
+ typename DylibLookupFtor>
+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 <typename BaseRTDyldMM, typename ExternalLookupFtor,
+ typename DylibLookupFtor>
+std::unique_ptr<
+ LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>>
+createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup,
+ DylibLookupFtor &&DylibLookup) {
+ typedef LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>
+ ThisLookasideMM;
+ return llvm::make_unique<ThisLookasideMM>(
+ std::forward<ExternalLookupFtor>(ExternalLookup),
+ std::forward<DylibLookupFtor>(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 <list>
+#include <memory>
+
+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<RTDyldMemoryManager> MM)
+ : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*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<RuntimeDyld::LoadedObjectInfo>
+ 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<MemoryBuffer> B) {
+ OwnedBuffers.push_back(std::move(B));
+ }
+
+ private:
+ std::unique_ptr<RTDyldMemoryManager> MM;
+ std::unique_ptr<RuntimeDyld> 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<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
+ };
+
+ typedef std::list<LinkedObjectSet> 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 <typename OwningMBSet>
+ 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 <typename ObjSetT, typename LoadResult>
+ 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 <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
+class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+public:
+
+ /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
+ /// RuntimeDyld::LoadedObjectInfo instances.
+ typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
+ LoadedObjInfoList;
+
+ /// @brief Functor to create RTDyldMemoryManager instances.
+ typedef std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateRTDyldMMFtor;
+
+ /// @brief Functor for receiving finalization notifications.
+ typedef std::function<void(ObjSetHandleT)> 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 <typename ObjSetT>
+ ObjSetHandleT addObjectSet(const ObjSetT &Objects,
+ std::unique_ptr<RTDyldMemoryManager> 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<OrcX86_64> &JCBM);
+
+ /// @brief Get a label name from the given index.
+ typedef std::function<std::string(unsigned)> 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 <cstdlib>
+
+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 <memory>
namespace llvm {
namespace object {
class ObjectFile;
+ template <typename T> 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<object::ObjectFile>
+ 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<ObjectImage>
- loadObject(std::unique_ptr<ObjectBuffer> 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<ObjectImage>
- loadObject(std::unique_ptr<object::ObjectFile> InputObject);
+ /// Add the referenced object file to the list of objects to be loaded and
+ /// relocated.
+ std::unique_ptr<LoadedObjectInfo> 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, Function>;
- 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<BasicBlock*>(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<BasicBlock*>(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<BasicBlock, Value::user_iterator> pred_iterator;
typedef PredIterator<const BasicBlock,
Value::const_user_iterator> const_pred_iterator;
+typedef llvm::iterator_range<pred_iterator> pred_range;
+typedef llvm::iterator_range<const_pred_iterator> 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<TerminatorInst*, BasicBlock> succ_iterator;
typedef SuccIterator<const TerminatorInst*,
const BasicBlock> succ_const_iterator;
+typedef llvm::iterator_range<succ_iterator> succ_range;
+typedef llvm::iterator_range<succ_const_iterator> 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 <typename T, typename U> struct isPodLike<SuccIterator<T, U> > {
static const bool value = isPodLike<T>::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<Comdat> *Name);
- Comdat(const Comdat &) LLVM_DELETED_FUNCTION;
+ Comdat(const Comdat &) = delete;
// Points to the map in Module.
StringMapEntry<Comdat> *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 <class ConstantClass> 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>;
- ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION;
+ ConstantArray(const ConstantArray &) = delete;
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
public:
@@ -380,7 +383,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
//
class ConstantStruct : public Constant {
friend struct ConstantAggrKeyType<ConstantStruct>;
- ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION;
+ ConstantStruct(const ConstantStruct &) = delete;
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
public:
@@ -439,7 +442,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
///
class ConstantVector : public Constant {
friend struct ConstantAggrKeyType<ConstantVector>;
- ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION;
+ ConstantVector(const ConstantVector &) = delete;
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> 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<float> Elts);
static Constant *get(LLVMContext &Context, ArrayRef<double> 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<uint16_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> 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<float> Elts);
static Constant *get(LLVMContext &Context, ArrayRef<double> 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<uint16_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts);
+ static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> 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<Value *, 4> AllEnumTypes;
- /// Use TrackingVH to collect RetainTypes, since they can be updated
- /// later on.
- SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes;
- SmallVector<Value *, 4> AllSubprograms;
- SmallVector<Value *, 4> AllGVs;
- SmallVector<TrackingVH<MDNode>, 4> AllImportedModules;
+ SmallVector<Metadata *, 4> AllEnumTypes;
+ /// Track the RetainTypes, since they can be updated later on.
+ SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
+ SmallVector<Metadata *, 4> AllSubprograms;
+ SmallVector<Metadata *, 4> AllGVs;
+ SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
+
+ /// \brief Track nodes that may be unresolved.
+ SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
+ bool AllowUnresolvedNodes;
/// Each subprogram's preserved local variables.
- DenseMap<MDNode *, std::vector<TrackingVH<MDNode>>> PreservedVariables;
+ DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> 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<Value *> Elements);
+ DIArray getOrCreateArray(ArrayRef<Metadata *> Elements);
/// getOrCreateTypeArray - Get a DITypeArray, create one if required.
- DITypeArray getOrCreateTypeArray(ArrayRef<Value *> Elements);
+ DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> 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<int64_t> Addr = None);
+ DIExpression createExpression(ArrayRef<uint64_t> Addr = None);
+ DIExpression createExpression(ArrayRef<int64_t> 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 <class T> 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<unsigned> &SplitFlags);
+
protected:
const MDNode *DbgNode;
@@ -168,42 +172,47 @@ public:
bool Verify() const;
- operator MDNode *() const { return const_cast<MDNode *>(DbgNode); }
- MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); }
+ MDNode *get() const { return const_cast<MDNode *>(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 <class T> T getHeaderFieldAs(unsigned Index) const {
- T Int;
- if (getHeaderField(Index).getAsInteger(0, Int))
- return 0;
- return Int;
+ return getHeaderIterator(Index).getNumber<T>();
}
uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(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<MDNode>(VALID)); \
+ return DESC(static_cast<const MDNode *>(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<T>(Idx);
- }
+ T getElement(unsigned Idx) const { return getFieldAs<T>(Idx); }
};
typedef DITypedArray<DIDescriptor> DIArray;
@@ -282,6 +302,7 @@ public:
};
template <typename T> class DIRef;
+typedef DIRef<DIDescriptor> DIDescriptorRef;
typedef DIRef<DIScope> DIScopeRef;
typedef DIRef<DIType> DITypeRef;
typedef DITypedArray<DITypeRef> DITypeArray;
@@ -371,6 +392,12 @@ template <typename T> StringRef DIRef<T>::getName() const {
return MS->getString();
}
+/// \brief Handle fields that are references to DIDescriptors.
+template <>
+DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const;
+/// \brief Specialize DIRef constructor for DIDescriptorRef.
+template <> DIRef<DIDescriptor>::DIRef(const Metadata *V);
+
/// \brief Handle fields that are references to DIScopes.
template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
/// \brief Specialize DIRef constructor for DIScopeRef.
@@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
/// \brief Specialize DIRef constructor for DITypeRef.
template <> DIRef<DIType>::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<DIScopeRef>(2); }
StringRef getName() const { return getHeaderField(1); }
- unsigned getLineNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
- uint64_t getSizeInBits() const {
- return getHeaderFieldAs<unsigned>(3);
- }
- uint64_t getAlignInBits() const {
- return getHeaderFieldAs<unsigned>(4);
- }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ uint64_t getSizeInBits() const { return getHeaderFieldAs<unsigned>(3); }
+ uint64_t getAlignInBits() const { return getHeaderFieldAs<unsigned>(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<unsigned>(5);
- }
+ uint64_t getOffsetInBits() const { return getHeaderFieldAs<unsigned>(5); }
unsigned getFlags() const { return getHeaderFieldAs<unsigned>(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<DIArray>(4);
}
+
+private:
template <typename T>
void setArrays(DITypedArray<T> 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<unsigned>(7);
- }
+
+public:
+ unsigned getRunTimeLang() const { return getHeaderFieldAs<unsigned>(7); }
DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); }
+private:
/// \brief Set the containing type.
void setContainingType(DICompositeType ContainingType);
+
+public:
DIArray getTemplateParams() const { return getFieldAs<DIArray>(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<DIScope>(2); }
- unsigned getLineNumber() const {
- return getHeaderFieldAs<unsigned>(1);
- }
- unsigned getColumnNumber() const {
- return getHeaderFieldAs<unsigned>(2);
- }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(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<unsigned>(2); }
- unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(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<unsigned>(2); }
- unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- Value *getValue() const;
- StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
- StringRef getDirectory() const {
- return getFieldAs<DIFile>(4).getDirectory();
- }
+ Metadata *getValue() const;
bool Verify() const;
};
@@ -763,7 +772,7 @@ public:
unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); }
unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); }
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); }
StringRef getDirectory() const {
return getFieldAs<DIFile>(2).getDirectory();
@@ -807,11 +816,6 @@ public:
return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0;
}
- /// \brief Return true if this variable is represented as a pointer.
- bool isIndirect() const {
- return (getHeaderFieldAs<unsigned>(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<uint64_t>();
+ }
+ operator uint64_t () const { return I.getNumber<uint64_t>(); }
+ /// \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<std::input_iterator_tag, StringRef,
+ unsigned, const Operand*, Operand> {
+ 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<MDLocation>(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<DIScope>(2); }
- DILocation getOrigLocation() const { return getFieldAs<DILocation>(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<DILexicalBlockFile>(2).getDiscriminator()
+ ? DILexicalBlockFile(
+ cast<MDNode>(cast<MDLocation>(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<DIScope>(1); }
- DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
+ DIDescriptorRef getEntity() const { return getFieldAs<DIDescriptorRef>(2); }
unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(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<DICompileUnit>::const_iterator compile_unit_iterator;
typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator;
- typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator;
+ typedef SmallVectorImpl<DIGlobalVariable>::const_iterator
+ global_variable_iterator;
typedef SmallVectorImpl<DIType>::const_iterator type_iterator;
typedef SmallVectorImpl<DIScope>::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<Metadata *> 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<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
+ : MDNode(C, ID, Storage, Ops1, Ops2) {
+ assert(Tag < 1u << 16);
+ SubclassData16 = Tag;
+ }
+ ~DebugNode() {}
+
+ template <class Ty> Ty *getOperandAs(unsigned I) const {
+ return cast_or_null<Ty>(getOperand(I));
+ }
+
+ StringRef getStringOperand(unsigned I) const {
+ if (auto *S = getOperandAs<MDString>(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<Metadata *> Ops1,
+ ArrayRef<Metadata *> 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<Metadata *> 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<Metadata *> DwarfOps,
+ StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempGenericDebugNode cloneImpl() const {
+ return getTemporary(
+ getContext(), getTag(), getHeader(),
+ SmallVector<Metadata *, 4>(dwarf_op_begin(), dwarf_op_end()));
+ }
+
+public:
+ unsigned getHash() const { return SubclassData32; }
+
+ DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header,
+ ArrayRef<Metadata *> DwarfOps),
+ (Tag, Header, DwarfOps))
+ DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header,
+ ArrayRef<Metadata *> 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<Metadata *> 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<MDString>(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<Metadata *> 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<Metadata *> 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<MDString>(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<Metadata *> 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<Metadata *> 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<Metadata *> 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<Metadata *> 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<MDString>(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<MDTuple>(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<Metadata *> 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<Metadata *> 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<Metadata *> 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<MDString>(0); }
+ MDString *getRawDirectory() const { return getOperandAs<MDString>(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<Metadata *> 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<MDString>(1); }
+ MDString *getRawFlags() const { return getOperandAs<MDString>(2); }
+ MDString *getRawSplitDebugFilename() const {
+ return getOperandAs<MDString>(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<Metadata *> 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<MDString>(2); }
+ MDString *getRawLinkageName() const { return getOperandAs<MDString>(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<Metadata *> 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<Metadata *> 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<Metadata *> 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<Metadata *> 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<MDString>(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<Metadata *> 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<MDString>(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<Metadata *> 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<Metadata *> 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<Metadata *> 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<MDString>(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<Metadata *> 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<MDString>(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<Metadata *> 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<uint64_t> Elements;
+
+ MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
+ : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None),
+ Elements(Elements.begin(), Elements.end()) {}
+ ~MDExpression() {}
+
+ static MDExpression *getImpl(LLVMContext &Context,
+ ArrayRef<uint64_t> Elements, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempMDExpression cloneImpl() const {
+ return getTemporary(getContext(), getElements());
+ }
+
+public:
+ DEFINE_MDNODE_GET(MDExpression, (ArrayRef<uint64_t> Elements), (Elements))
+
+ TempMDExpression clone() const { return cloneImpl(); }
+
+ ArrayRef<uint64_t> 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<uint64_t>::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<std::input_iterator_tag, ExprOperand> {
+ 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<Metadata *> 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<MDString>(0); }
+ MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
+ MDString *getRawSetterName() const { return getOperandAs<MDString>(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<Metadata *> 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<MDString>(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 <typename T> 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<DebugLoc>;
-
- /// 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<DebugLoc> {
- 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<Type*> 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<Type *> 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<Type *> 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<void(const DiagnosticInfo &)> 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 <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
@@ -69,6 +74,13 @@ public:
DominatorTree() : DominatorTreeBase<BasicBlock>(false) {}
+ DominatorTree(DominatorTree &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
+ DominatorTree &operator=(DominatorTree &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(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<DominatorTree*>
};
/// \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<Function> *AM);
+
+ static StringRef name() { return "DominatorTreePrinterPass"; }
+};
+
+/// \brief Verifier pass for the \c DominatorTree.
+struct DominatorTreeVerifierPass {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *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<Function, Module>;
@@ -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<CallingConv::ID>(getSubclassDataFromValue() >> 2);
+ return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3);
}
void setCallingConv(CallingConv::ID CC) {
- setValueSubclassData((getSubclassDataFromValue() & 3) |
- (static_cast<unsigned>(CC) << 2));
+ setValueSubclassData((getSubclassDataFromValue() & 7) |
+ (static_cast<unsigned>(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 <system_error>
+#include <vector>
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<StructType *> 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<typename ValueSubClass, typename ItemParentClass>
class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
friend class SymbolTableListTraits<GlobalAlias, Module>;
- 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 <system_error>
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<typename ValueSubClass, typename ItemParentClass>
class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
friend class SymbolTableListTraits<GlobalVariable, Module>;
- 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<Value *> CallArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> 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<Use> CallArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> 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<Value *> 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>;
- 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<const iplist<BasicBlock>,
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_iterator> inst_range(Function *F) {
+ return iterator_range<inst_iterator>(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<const_inst_iterator> inst_range(const Function *F) {
+ return iterator_range<const_inst_iterator>(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_iterator> inst_range(Function &F) {
+ return iterator_range<inst_iterator>(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<const_inst_iterator> inst_range(const Function &F) {
+ return iterator_range<const_inst_iterator>(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<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits;
class Instruction : public User, public ilist_node<Instruction> {
- 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<SequentialType>(Instruction::getType());
}
+ Type *getSourceElementType() const {
+ SequentialType *Ty = cast<SequentialType>(getPointerOperandType());
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ Ty = cast<SequentialType>(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<unsigned, 4> 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<unsigned> 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<MDNode>(getArgOperand(1)); }
- MDNode *getExpression() const { return cast<MDNode>(getArgOperand(2)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(1))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(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<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
}
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
- MDNode *getExpression() const { return cast<MDNode>(getArgOperand(3)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(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<Value*>(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<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+
+ GlobalVariable *getName() const {
+ return cast<GlobalVariable>(
+ const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
+ }
+
+ ConstantInt *getHash() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
+ }
+
+ ConstantInt *getNumCounters() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
+ }
+
+ ConstantInt *getIndex() const {
+ return cast<ConstantInt>(const_cast<Value *>(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<Type*> 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<IITDescriptor> &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<int num>
// the intrinsic is overloaded, so the matched type should be declared as iAny.
class LLVMExtendedType<int num> : LLVMMatchType<num>;
class LLVMTruncatedType<int num> : LLVMMatchType<num>;
+class LLVMVectorSameWidth<int num, LLVMType elty>
+ : LLVMMatchType<num> {
+ ValueType ElTy = elty.VT;
+}
+class LLVMPointerTo<int num> : LLVMMatchType<num>;
+class LLVMVectorOfPointersToElt<int num> : LLVMMatchType<num>;
// 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<int num> : LLVMMatchType<num>;
def llvm_void_ty : LLVMType<isVoid>;
+def llvm_any_ty : LLVMType<Any>;
def llvm_anyint_ty : LLVMType<iAny>;
def llvm_anyfloat_ty : LLVMType<fAny>;
def llvm_anyvector_ty : LLVMType<vAny>;
@@ -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<string GCCIntSuffix>
//
class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [llvm_i1_ty], [llvm_i1_ty, llvm_i1_ty, llvm_i1_ty],
[IntrNoMem]>;
//
// DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) ->
@@ -434,7 +434,7 @@ class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix>
class Hexagon_sf_si_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_sf_df_Intrinsic<string GCCIntSuffix>
//
@@ -490,21 +490,21 @@ class Hexagon_si_df_Intrinsic<string GCCIntSuffix>
class Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_float_ty, llvm_float_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_float_ty, llvm_float_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_float_ty, llvm_float_ty],
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty],
+ [IntrNoMem, Throws]>;
//
// Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix>
//
@@ -519,7 +519,7 @@ class Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_float_ty], [llvm_float_ty, llvm_float_ty,
llvm_float_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix>
//
@@ -528,7 +528,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix>
[llvm_float_ty], [llvm_float_ty, llvm_float_ty,
llvm_float_ty,
llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_di_dididi_Intrinsic<string GCCIntSuffix>
//
@@ -543,7 +543,7 @@ class Hexagon_di_dididisi_Intrinsic<string GCCIntSuffix>
class Hexagon_df_si_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_df_di_Intrinsic<string GCCIntSuffix>
//
@@ -571,21 +571,21 @@ class Hexagon_df_df_Intrinsic<string GCCIntSuffix>
class Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_double_ty, llvm_double_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_double_ty, llvm_double_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_double_ty, llvm_double_ty],
+ [IntrNoMem, Throws]>;
//
-// Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix>
+// Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix>
//
-class Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix>
+class Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i1_ty], [llvm_double_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty],
+ [IntrNoMem, Throws]>;
//
//
// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
@@ -594,7 +594,7 @@ class Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
[llvm_double_ty], [llvm_double_ty, llvm_double_ty,
llvm_double_ty],
- [IntrNoMem]>;
+ [IntrNoMem, Throws]>;
//
// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix>
//
@@ -603,7 +603,7 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix>
[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<llvm_i32_ty>;
+def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>;
+
+// 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<string GCCIntSuffix, list<LLVMType> ret_types,
+ list<LLVMType> param_types,
+ list<IntrinsicProperty> properties>
+ : GCCBuiltin<!strconcat("__builtin_qpx_", GCCIntSuffix)>,
+ Intrinsic<ret_types, param_types, properties>;
+}
+
+//===----------------------------------------------------------------------===//
+// 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<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>;
+
+/// 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<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty],
+ [IntrNoMem]>;
+
+/// 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<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and returns a v4f64.
+class PowerPC_QPX_Load_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+
+/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and returns a v4f64 permutation.
+class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f64_ty], [llvm_ptr_ty], [IntrNoMem]>;
+
+/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer
+/// and stores a v4f64.
+class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix>
+ : PowerPC_QPX_Intrinsic<GCCIntSuffix,
+ [], [llvm_v4f64_ty, llvm_ptr_ty],
+ [IntrReadWriteArgMem]>;
+
+//===----------------------------------------------------------------------===//
+// 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 <string>
-
-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<ImmutablePass *, 16> ImmutablePasses;
DenseMap<Pass *, AnalysisUsage *> 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<AnalysisID, const PassInfo *> 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<const PassInfo*> {
- cl::Option *Opt;
public:
- PassNameParser();
+ PassNameParser(cl::Option &O);
virtual ~PassNameParser();
- void initialize(cl::Option &O) {
- Opt = &O;
- cl::parser<const PassInfo*>::initialize(O);
+ void initialize() {
+ cl::parser<const PassInfo*>::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 <typename T> 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 <type_traits>
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<void *, std::pair<OwnerTy, uint64_t>, 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<ConstantAsMetadata>(get(C));
+ }
+ static LocalAsMetadata *getLocal(Value *Local) {
+ return cast<LocalAsMetadata>(get(Local));
+ }
+
+ static ValueAsMetadata *getIfExists(Value *V);
+ static ConstantAsMetadata *getConstantIfExists(Value *C) {
+ return cast_or_null<ConstantAsMetadata>(getIfExists(C));
+ }
+ static LocalAsMetadata *getLocalIfExists(Value *Local) {
+ return cast_or_null<LocalAsMetadata>(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<Constant>(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<Constant>(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<ConstantInt>(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<MDInt>(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<ConstantInt>(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 <class T> T &make();
+template <class T, class Result> struct HasDereference {
+ typedef char Yes[1];
+ typedef char No[2];
+ template <size_t N> struct SFINAE {};
+
+ template <class U, class V>
+ static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0);
+ template <class U, class V> static No &hasDereference(...);
+
+ static const bool value =
+ sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes);
+};
+template <class V, class M> struct IsValidPointer {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ HasDereference<M, const Metadata &>::value;
+};
+template <class V, class M> struct IsValidReference {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ std::is_convertible<M, const Metadata &>::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 <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type
+hasa(Y &&MD) {
+ assert(MD && "Null pointer sent into hasa");
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return isa<X>(V->getValue());
+ return false;
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::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 <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract(Y &&MD) {
+ return cast<X>(cast<ConstantAsMetadata>(MD)->getValue());
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::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 <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract_or_null(Y &&MD) {
+ if (auto *V = cast_or_null<ConstantAsMetadata>(MD))
+ return cast<X>(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 <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract(Y &&MD) {
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(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 <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract_or_null(Y &&MD) {
+ if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+} // end namespace mdconst
+
//===----------------------------------------------------------------------===//
/// \brief A single uniqued string.
///
@@ -60,14 +464,13 @@ public:
class MDString : public Metadata {
friend class StringMapEntry<MDString>;
- 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<MDString> *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<AAMDNodes> {
}
};
-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<void *>(this) == &MD && "Expected same address");
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+};
+
+template <> struct simplify_type<MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const MDOperand> {
+ 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<LLVMContext *, ReplaceableMetadataImpl *> 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<ReplaceableMetadataImpl> 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<ReplaceableMetadataImpl *>();
+ }
+ LLVMContext &getContext() const {
+ if (hasReplaceableUses())
+ return getReplaceableUses()->getContext();
+ return *Ptr.get<LLVMContext *>();
+ }
+ ReplaceableMetadataImpl *getReplaceableUses() const {
+ if (hasReplaceableUses())
+ return Ptr.get<ReplaceableMetadataImpl *>();
+ 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<ReplaceableMetadataImpl> 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<ReplaceableMetadataImpl> takeReplaceableUses() {
+ assert(hasReplaceableUses() && "Expected to own replaceable uses");
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses(
+ getReplaceableUses());
+ Ptr = &ReplaceableUses->getContext();
+ return ReplaceableUses;
+ }
+};
+
+struct TempMDNodeDeleter {
+ inline void operator()(MDNode *Node) const;
+};
+
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ typedef std::unique_ptr<CLASS, TempMDNodeDeleter> 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<Metadata *> Ops1, ArrayRef<Metadata *> 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<MDOperand *>(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<Metadata *> MDs);
+ static inline MDTuple *getIfExists(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+ static inline MDTuple *getDistinct(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+ static inline TempMDTuple getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
- MDNode(LLVMContext &C, unsigned ID, ArrayRef<Value *> Vals,
- bool isFunctionLocal);
- ~MDNode() {}
+ /// \brief Create a (temporary) clone of this.
+ TempMDNode clone() const;
- static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals,
- FunctionLocalness FL, bool Insert = true);
-public:
- static MDNode *get(LLVMContext &Context, ArrayRef<Value*> 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<Value*> 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<Value*> 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<Value*> 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 <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(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 <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(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 <class T>
+ static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type
+ replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) {
+ return cast<T>(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 <class T, class StoreT>
+ 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 <class NodeTy> struct HasCachedHash;
+ template <class NodeTy>
+ static void dispatchRecalculateHash(NodeTy *N, std::true_type) {
+ N->recalculateHash();
+ }
+ template <class NodeTy>
+ static void dispatchRecalculateHash(NodeTy *N, std::false_type) {}
+ template <class NodeTy>
+ static void dispatchResetHash(NodeTy *N, std::true_type) {
+ N->setHash(0);
+ }
+ template <class NodeTy>
+ static void dispatchResetHash(NodeTy *N, std::false_type) {}
+
+public:
+ typedef const MDOperand *op_iterator;
+ typedef iterator_range<op_iterator> op_range;
+
+ op_iterator op_begin() const {
+ return const_cast<MDNode *>(this)->mutable_begin();
+ }
+ op_iterator op_end() const {
+ return const_cast<MDNode *>(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<Metadata *> Vals)
+ : MDNode(C, MDTupleKind, Storage, Vals) {
+ setHash(Hash);
+ }
+ ~MDTuple() { dropAllReferences(); }
- unsigned Hash;
+ void setHash(unsigned Hash) { SubclassData32 = Hash; }
+ void recalculateHash();
- GenericMDNode(LLVMContext &C, ArrayRef<Value *> Vals, bool isFunctionLocal)
- : MDNode(C, GenericMDNodeVal, Vals, isFunctionLocal), Hash(0) {}
- ~GenericMDNode();
+ static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ StorageType Storage, bool ShouldCreate = true);
- void dropAllReferences();
+ TempMDTuple cloneImpl() const {
+ return getTemporary(getContext(),
+ SmallVector<Metadata *, 4>(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<Metadata *> MDs) {
+ return getImpl(Context, MDs, Uniqued);
+ }
+ static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> 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<Metadata *> MDs) {
+ return getImpl(Context, MDs, Distinct);
+ }
- MDNodeFwdDecl(LLVMContext &C, ArrayRef<Value *> 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<Metadata *> 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<Metadata *> MDs) {
+ return MDTuple::get(Context, MDs);
+}
+MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getIfExists(Context, MDs);
+}
+MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getDistinct(Context, MDs);
+}
+TempMDTuple MDNode::getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> 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<NamedMDNode> {
friend struct ilist_traits<NamedMDNode>;
friend class LLVMContextImpl;
friend class Module;
- NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION;
+ NamedMDNode(const NamedMDNode &) = delete;
std::string Name;
Module *Parent;
- void *Operands; // SmallVector<TrackingVH<MDNode>, 4>
+ void *Operands; // SmallVector<TrackingMDRef, 4>
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 <type_traits>
+
+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<Metadata *>(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<MetadataAsValue *, Metadata *> 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<typename T> struct DenseMapInfo;
-template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap;
template<> struct ilist_traits<Function>
: public SymbolTableListTraits<Function, Module> {
@@ -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=<uint64> 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=<uint64> 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<StructType *> 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<Operator, Instruction::BitCast> {
+ 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 <list>
#include <memory>
@@ -91,9 +94,12 @@ public:
}
/// \brief Mark a particular pass as preserved, adding it to the set.
- template <typename PassT> void preserve() {
+ template <typename PassT> 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<void *, 2> 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 <typename IRUnitT, typename AnalysisManagerT> 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 <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- typename ResultT>
-class PassRunAcceptsAnalysisManager {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::run> *);
- template <typename T> static BigType f(...);
+// Forward declare the analysis manager template.
+template <typename IRUnitT> class AnalysisManager;
-public:
- enum { Value = sizeof(f<PassT>(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 <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value>
-struct PassModel;
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- 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 <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- 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 <typename IRUnitT> 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 <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
- template <typename T> static BigType f(...);
-
+/// If it is run with an \c AnalysisManager<IRUnitT> 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 <typename IRUnitT> class PassManager {
public:
- enum { Value = sizeof(f<ResultT>(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 <typename IRUnitT, typename PassT, typename ResultT,
- bool HasInvalidateHandler =
- ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
-struct AnalysisResultModel;
-
-/// \brief Specialization of \c AnalysisResultModel which provides the default
-/// invalidate functionality.
-template <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, false>
- : AnalysisResultConcept<IRUnitT> {
- 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 <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, true>
- : AnalysisResultConcept<IRUnitT> {
- 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<IRUnitT> *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 <typename IRUnitT, typename AnalysisManagerT>
-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<AnalysisResultConcept<IRUnitT>>
- 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 <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value>
-struct AnalysisPassModel;
-
-/// \brief Specialization of \c AnalysisPassModel which passes an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- 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<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
-
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *AM) override {
- return make_unique<ResultModelT>(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 <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- 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<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
-
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *) override {
- return make_unique<ResultModelT>(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 <typename ModulePassT> void addPass(ModulePassT Pass) {
- Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass)));
+ template <typename PassT> void addPass(PassT Pass) {
+ typedef detail::PassModel<IRUnitT, PassT> 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<Module *, ModuleAnalysisManager>
- ModulePassConcept;
- template <typename PassT>
- struct ModulePassModel
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT> {
- ModulePassModel(PassT Pass)
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
-
- ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION;
- ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION;
+ typedef detail::PassConcept<IRUnitT> PassConceptT;
- std::vector<std::unique_ptr<ModulePassConcept>> Passes;
-};
+ PassManager(const PassManager &) = delete;
+ PassManager &operator=(const PassManager &) = delete;
-class FunctionAnalysisManager;
+ std::vector<std::unique_ptr<PassConceptT>> 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 <typename FunctionPassT> void addPass(FunctionPassT Pass) {
- Passes.emplace_back(new FunctionPassModel<FunctionPassT>(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<Function *, FunctionAnalysisManager>
- FunctionPassConcept;
- template <typename PassT>
- struct FunctionPassModel
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT> {
- FunctionPassModel(PassT Pass)
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
+/// \brief Convenience typedef for a pass manager over modules.
+typedef PassManager<Module> ModulePassManager;
- FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
- FunctionPassManager &
- operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
-
- std::vector<std::unique_ptr<FunctionPassConcept>> Passes;
-};
+/// \brief Convenience typedef for a pass manager over functions.
+typedef PassManager<Function> 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 <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
DerivedT *derived_this() { return static_cast<DerivedT *>(this); }
const DerivedT *derived_this() const {
return static_cast<const DerivedT *>(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<IRUnitT> ResultConceptT;
- typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT;
+ typedef detail::AnalysisPassConcept<IRUnitT> 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> typename PassT::Result &getResult(IRUnitT IR) {
+ template <typename PassT> 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>
- 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 <typename PassT> void registerPass(PassT Pass) {
assert(!AnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!");
- typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT;
+ typedef detail::AnalysisPassModel<IRUnitT, PassT> 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 <typename PassT> void invalidate(Module *M) {
+ template <typename PassT> 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<ModuleAnalysisManager, Module *> {
- friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>;
- typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> 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<BaseT &>(Arg))),
- ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {}
- ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) {
- BaseT::operator=(std::move(static_cast<BaseT &>(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<void *,
- std::unique_ptr<detail::AnalysisResultConcept<Module *>>>
- 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<FunctionAnalysisManager, Function *> {
- friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>;
- typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>
- 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 <typename IRUnitT>
+class AnalysisManager
+ : public detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> {
+ friend class detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT>;
+ typedef detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, 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<BaseT &>(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<BaseT &>(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<void *, 8> 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<std::pair<
- void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>>
- FunctionAnalysisResultListT;
+ void *, std::unique_ptr<detail::AnalysisResultConcept<IRUnitT>>>>
+ AnalysisResultListT;
/// \brief Map type from function pointer to our custom list type.
- typedef DenseMap<Function *, FunctionAnalysisResultListT>
- FunctionAnalysisResultListMapT;
+ typedef DenseMap<IRUnitT *, AnalysisResultListT> 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<std::pair<void *, Function *>,
- FunctionAnalysisResultListT::iterator>
- FunctionAnalysisResultMapT;
+ typedef DenseMap<std::pair<void *, IRUnitT *>,
+ 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<Module> ModuleAnalysisManager;
+
+/// \brief Convenience typedef for the Function analysis manager.
+typedef AnalysisManager<Function> 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 <typename FunctionPassT> 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<FunctionAnalysisManagerModuleProxy>(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<FunctionPassT>(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 <typename AnalysisT> 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 <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
+ if (AM)
+ (void)AM->template getResult<AnalysisT>(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 <typename AnalysisT> 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 <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *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<AnalysisT>(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 <typename IRUnitT> 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 <typename IRUnitT> 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 <typename IRUnitT> 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<IRUnitT> *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<IRUnitT>.
+template <typename IRUnitT, typename PassT, typename ResultT>
+class PassRunAcceptsAnalysisManager {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::run> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<PassT>(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<IRUnitT>*, we pass it
+/// along.
+template <typename IRUnitT, typename PassT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, PreservedAnalysesT>::Value>
+struct PassModel;
+
+/// \brief Specialization of \c PassModel for passes that accept an analyis
+/// manager.
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
+ : PassConcept<IRUnitT> {
+ 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<IRUnitT> *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 <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false>
+ : PassConcept<IRUnitT> {
+ 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<IRUnitT> *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 <typename IRUnitT> 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 <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<ResultT>(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 <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool HasInvalidateHandler =
+ ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
+struct AnalysisResultModel;
+
+/// \brief Specialization of \c AnalysisResultModel which provides the default
+/// invalidate functionality.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
+ : AnalysisResultConcept<IRUnitT> {
+ 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 <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
+ : AnalysisResultConcept<IRUnitT> {
+ 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 <typename IRUnitT> 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<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *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 <typename IRUnitT, typename PassT,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, typename PassT::Result>::Value>
+struct AnalysisPassModel;
+
+/// \brief Specialization of \c AnalysisPassModel which passes an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
+ 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<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return make_unique<ResultModelT>(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 <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> {
+ 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<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override {
+ return make_unique<ResultModelT>(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<typename Val, typename Pattern>
-bool match(Val *V, const Pattern &P) {
- return const_cast<Pattern&>(P).match(V);
+template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) {
+ return const_cast<Pattern &>(P).match(V);
}
-
-template<typename SubPattern_t>
-struct OneUse_match {
+template <typename SubPattern_t> struct OneUse_match {
SubPattern_t SubPattern;
OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
return V->hasOneUse() && SubPattern.match(V);
}
};
-template<typename T>
-inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; }
-
+template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) {
+ return SubPattern;
+}
-template<typename Class>
-struct class_match {
- template<typename ITy>
- bool match(ITy *V) { return isa<Class>(V); }
+template <typename Class> struct class_match {
+ template <typename ITy> bool match(ITy *V) { return isa<Class>(V); }
};
-/// m_Value() - Match an arbitrary value and ignore it.
+/// \brief Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }
-/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it.
+
+/// \brief Match an arbitrary binary operation and ignore it.
+inline class_match<BinaryOperator> m_BinOp() {
+ return class_match<BinaryOperator>();
+}
+
+/// \brief Matches any compare instruction and ignore it.
+inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }
+
+/// \brief Match an arbitrary ConstantInt and ignore it.
inline class_match<ConstantInt> m_ConstantInt() {
return class_match<ConstantInt>();
}
-/// m_Undef() - Match an arbitrary undef constant.
+
+/// \brief Match an arbitrary undef constant.
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
+/// \brief Match an arbitrary Constant and ignore it.
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
/// Matching combinators
-template<typename LTy, typename RTy>
-struct match_combine_or {
+template <typename LTy, typename RTy> 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<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> bool match(ITy *V) {
if (L.match(V))
return true;
if (R.match(V))
@@ -95,15 +98,13 @@ struct match_combine_or {
}
};
-template<typename LTy, typename RTy>
-struct match_combine_and {
+template <typename LTy, typename RTy> 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<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> 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<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) {
return match_combine_or<LTy, RTy>(L, R);
}
/// Combine two pattern matchers matching L && R
-template<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) {
return match_combine_and<LTy, RTy>(L, R);
}
struct match_zero {
- template<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(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<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(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<match_zero, match_neg_zero> m_AnyZero() {
@@ -161,16 +160,14 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
struct apint_match {
const APInt *&Res;
apint_match(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CI = dyn_cast<ConstantInt>(V)) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue())) {
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(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<int64_t Val>
-struct constantint_match {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+template <int64_t Val> struct constantint_match {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V)) {
const APInt &CIV = CI->getValue();
if (Val >= 0)
return CIV == static_cast<uint64_t>(Val);
@@ -200,45 +194,39 @@ struct constantint_match {
}
};
-/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value.
-template<int64_t Val>
-inline constantint_match<Val> m_ConstantInt() {
+/// \brief Match a ConstantInt with a specific value.
+template <int64_t Val> inline constantint_match<Val> m_ConstantInt() {
return constantint_match<Val>();
}
-/// cst_pred_ty - This helper class is used to match scalar and vector constants
-/// that satisfy a specified predicate.
-template<typename Predicate>
-struct cst_pred_ty : public Predicate {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+/// \brief This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate.
+template <typename Predicate> struct cst_pred_ty : public Predicate {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
return this->isValue(CI->getValue());
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (const ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (const auto *CI = dyn_cast_or_null<ConstantInt>(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<typename Predicate>
-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 <typename Predicate> struct api_pred_ty : public Predicate {
const APInt *&Res;
api_pred_ty(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
if (this->isValue(CI->getValue())) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(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<is_one> m_One() { return cst_pred_ty<is_one>(); }
inline api_pred_ty<is_one> 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<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();}
+/// \brief Match an integer or vector with all bits set to true.
+inline cst_pred_ty<is_all_ones> m_AllOnes() {
+ return cst_pred_ty<is_all_ones>();
+}
inline api_pred_ty<is_all_ones> 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<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();}
+/// \brief Match an integer or vector with only the sign bit(s) set.
+inline cst_pred_ty<is_sign_bit> m_SignBit() {
+ return cst_pred_ty<is_sign_bit>();
+}
inline api_pred_ty<is_sign_bit> 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<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); }
inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; }
-template<typename Class>
-struct bind_ty {
+struct is_maxsignedvalue {
+ bool isValue(const APInt &C) { return C.isMaxSignedValue(); }
+};
+
+inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { return cst_pred_ty<is_maxsignedvalue>(); }
+inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { return V; }
+
+template <typename Class> struct bind_ty {
Class *&VR;
bind_ty(Class *&V) : VR(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (Class *CV = dyn_cast<Class>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CV = dyn_cast<Class>(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<Value> 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<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; }
+
+/// \brief Match a ConstantInt, capturing the value if we match.
inline bind_ty<ConstantInt> 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<Constant> 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<ConstantFP> 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<typename ITy>
- bool match(ITy *V) {
- return V == Val;
- }
+ template <typename ITy> 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<typename ITy>
- bool match(ITy *V) {
- if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CFP = dyn_cast<ConstantFP>(V))
return CFP->isExactlyValue(Val);
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CFP = dyn_cast_or_null<ConstantFP>(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<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CV = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CV = dyn_cast<ConstantInt>(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<typename ITy>
- bool match(ITy *V) {
- ConstantInt *CI = dyn_cast<ConstantInt>(V);
+ template <typename ITy> bool match(ITy *V) {
+ const auto *CI = dyn_cast<ConstantInt>(V);
if (!CI && V->getType()->isVectorTy())
if (const auto *C = dyn_cast<Constant>(V))
CI = dyn_cast_or_null<ConstantInt>(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 <typename LHS_t, typename RHS_t> struct AnyBinaryOp_match {
+ LHS_t L;
+ RHS_t R;
+
+ AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<BinaryOperator>(V))
+ return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
+ return false;
+ }
+};
+
+template <typename LHS, typename RHS>
+inline AnyBinaryOp_match<LHS, RHS> m_BinOp(const LHS &L, const RHS &R) {
+ return AnyBinaryOp_match<LHS, RHS>(L, R);
+}
+
+//===----------------------------------------------------------------------===//
// Matchers for specific binary operators.
//
-template<typename LHS_t, typename RHS_t, unsigned Opcode>
+template <typename LHS_t, typename RHS_t, unsigned Opcode>
struct BinaryOp_match {
LHS_t L;
RHS_t R;
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
R.match(CE->getOperand(1));
return false;
}
};
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Add>
-m_Add(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FAdd>
-m_FAdd(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Sub>
-m_Sub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FSub>
-m_FSub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Mul>
-m_Mul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FMul>
-m_FMul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::UDiv>
-m_UDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SDiv>
-m_SDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FDiv>
-m_FDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::URem>
-m_URem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SRem>
-m_SRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FRem>
-m_FRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::And>
-m_And(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::And>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Or>
-m_Or(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Xor>
-m_Xor(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Shl>
-m_Shl(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::LShr>
-m_LShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::AShr>
-m_AShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
}
-template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0>
+template <typename LHS_t, typename RHS_t, unsigned Opcode,
+ unsigned WrapFlags = 0>
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<typename OpTy>
- bool match(OpTy *V) {
- if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(V)) {
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *Op = dyn_cast<OverflowingBinaryOperator>(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<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
+template <typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
struct BinOp2_match {
LHS_t L;
RHS_t R;
BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opc1 ||
V->getValueID() == Value::InstructionVal + Opc2) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(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<typename LHS, typename RHS>
+/// \brief Matches LShr or AShr.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>
m_Shr(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R);
}
-/// m_LogicalShift - Matches LShr or Shl.
-template<typename LHS, typename RHS>
+/// \brief Matches LShr or Shl.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>
m_LogicalShift(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R);
}
-/// m_IDiv - Matches UDiv and SDiv.
-template<typename LHS, typename RHS>
+/// \brief Matches UDiv and SDiv.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>
m_IDiv(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R);
@@ -659,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) {
//===----------------------------------------------------------------------===//
// Class that matches exact binary ops.
//
-template<typename SubPattern_t>
-struct Exact_match {
+template <typename SubPattern_t> struct Exact_match {
SubPattern_t SubPattern;
Exact_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (PossiblyExactOperator *PEO = dyn_cast<PossiblyExactOperator>(V))
return PEO->isExact() && SubPattern.match(V);
return false;
}
};
-template<typename T>
-inline Exact_match<T> m_Exact(const T &SubPattern) { return SubPattern; }
+template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
+ return SubPattern;
+}
//===----------------------------------------------------------------------===//
// Matchers for CmpInst classes
//
-template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
+template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
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<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (Class *I = dyn_cast<Class>(V))
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
Predicate = I->getPredicate();
@@ -700,123 +712,114 @@ struct CmpClass_match {
}
};
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
+inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
+m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+}
+
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
}
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for SelectInst classes
//
-template<typename Cond_t, typename LHS_t, typename RHS_t>
+template <typename Cond_t, typename LHS_t, typename RHS_t>
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<typename OpTy>
- bool match(OpTy *V) {
- if (SelectInst *I = dyn_cast<SelectInst>(V))
- return C.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)) &&
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<SelectInst>(V))
+ return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) &&
R.match(I->getOperand(2));
return false;
}
};
-template<typename Cond, typename LHS, typename RHS>
-inline SelectClass_match<Cond, LHS, RHS>
-m_Select(const Cond &C, const LHS &L, const RHS &R) {
+template <typename Cond, typename LHS, typename RHS>
+inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L,
+ const RHS &R) {
return SelectClass_match<Cond, LHS, RHS>(C, L, R);
}
-/// m_SelectCst - This matches a select of two constants, e.g.:
-/// m_SelectCst<-1, 0>(m_Value(V))
-template<int64_t L, int64_t R, typename Cond>
-inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> >
+/// \brief This matches a select of two constants, e.g.:
+/// m_SelectCst<-1, 0>(m_Value(V))
+template <int64_t L, int64_t R, typename Cond>
+inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R>>
m_SelectCst(const Cond &C) {
return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>());
}
-
//===----------------------------------------------------------------------===//
// Matchers for CastInst classes
//
-template<typename Op_t, unsigned Opcode>
-struct CastClass_match {
+template <typename Op_t, unsigned Opcode> struct CastClass_match {
Op_t Op;
CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
return O->getOpcode() == Opcode && Op.match(O->getOperand(0));
return false;
}
};
-/// m_BitCast
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::BitCast>
-m_BitCast(const OpTy &Op) {
+/// \brief Matches BitCast.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::BitCast>(Op);
}
-/// m_PtrToInt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::PtrToInt>
-m_PtrToInt(const OpTy &Op) {
+/// \brief Matches PtrToInt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::PtrToInt>(Op);
}
-/// m_Trunc
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::Trunc>
-m_Trunc(const OpTy &Op) {
+/// \brief Matches Trunc.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::Trunc>(Op);
}
-/// m_SExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SExt>
-m_SExt(const OpTy &Op) {
+/// \brief Matches SExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SExt>(Op);
}
-/// m_ZExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::ZExt>
-m_ZExt(const OpTy &Op) {
+/// \brief Matches ZExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
}
-/// m_UIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::UIToFP>
-m_UIToFP(const OpTy &Op) {
+/// \brief Matches UIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::UIToFP>(Op);
}
-/// m_SIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SIToFP>
-m_SIToFP(const OpTy &Op) {
+/// \brief Matches SIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
@@ -824,46 +827,41 @@ m_SIToFP(const OpTy &Op) {
// Matchers for unary operators
//
-template<typename LHS_t>
-struct not_match {
+template <typename LHS_t> struct not_match {
LHS_t L;
not_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(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<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) ||
// FIXME: Remove CV.
isa<ConstantVector>(RHS)) &&
- cast<Constant>(RHS)->isAllOnesValue() &&
- L.match(LHS);
+ cast<Constant>(RHS)->isAllOnesValue() && L.match(LHS);
}
};
-template<typename LHS>
-inline not_match<LHS> m_Not(const LHS &L) { return L; }
+template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; }
-
-template<typename LHS_t>
-struct neg_match {
+template <typename LHS_t> struct neg_match {
LHS_t L;
neg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(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<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) ||
@@ -872,36 +870,33 @@ private:
}
};
-/// m_Neg - Match an integer negate.
-template<typename LHS>
-inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-
+/// \brief Match an integer negate.
+template <typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-template<typename LHS_t>
-struct fneg_match {
+template <typename LHS_t> struct fneg_match {
LHS_t L;
fneg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(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<ConstantFP>(LHS))
+ if (const auto *C = dyn_cast<ConstantFP>(LHS))
return C->isNegativeZeroValue() && L.match(RHS);
return false;
}
};
-/// m_FNeg - Match a floating point negate.
-template<typename LHS>
-inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
-
+/// \brief Match a floating point negate.
+template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) {
+ return L;
+}
//===----------------------------------------------------------------------===//
// Matchers for control flow.
@@ -909,13 +904,10 @@ inline fneg_match<LHS> 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<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(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<typename Cond_t>
-struct brc_match {
+template <typename Cond_t> 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<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(V))
if (BI->isConditional() && Cond.match(BI->getCondition())) {
T = BI->getSuccessor(0);
F = BI->getSuccessor(1);
@@ -946,31 +935,28 @@ struct brc_match {
}
};
-template<typename Cond_t>
+template <typename Cond_t>
inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
return brc_match<Cond_t>(C, T, F);
}
-
//===----------------------------------------------------------------------===//
// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y).
//
-template<typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
+template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
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<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
// Look for "(x pred y) ? x : y" or "(x pred y) ? y : x".
- SelectInst *SI = dyn_cast<SelectInst>(V);
+ auto *SI = dyn_cast<SelectInst>(V);
if (!SI)
return false;
- CmpInst_t *Cmp = dyn_cast<CmpInst_t>(SI->getCondition());
+ auto *Cmp = dyn_cast<CmpInst_t>(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<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>
-m_SMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> m_SMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>
-m_SMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> m_SMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>
-m_UMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> m_UMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>
-m_UMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(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<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>
-m_OrdFMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(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<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>
-m_OrdFMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(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<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>
m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(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<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
m_UnordFMin(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
}
-template<typename Opnd_t>
-struct Argument_match {
+template <typename Opnd_t> 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<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
CallSite CS(V);
return CS.isCall() && Val.match(CS.getArgument(OpI));
}
};
-/// Match an argument
-template<unsigned OpI, typename Opnd_t>
+/// \brief Match an argument.
+template <unsigned OpI, typename Opnd_t>
inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) {
return Argument_match<Opnd_t>(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<typename OpTy>
- bool match(OpTy *V) {
- if (const CallInst *CI = dyn_cast<CallInst>(V))
- if (const Function *F = CI->getCalledFunction())
+ template <typename OpTy> bool match(OpTy *V) {
+ if (const auto *CI = dyn_cast<CallInst>(V))
+ if (const auto *F = CI->getCalledFunction())
return F->getIntrinsicID() == ID;
return false;
}
@@ -1172,73 +1155,71 @@ struct IntrinsicID_match {
template <typename T0 = void, typename T1 = void, typename T2 = void,
typename T3 = void, typename T4 = void, typename T5 = void,
typename T6 = void, typename T7 = void, typename T8 = void,
- typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty;
-template <typename T0>
-struct m_Intrinsic_Ty<T0> {
- typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty;
+ typename T9 = void, typename T10 = void>
+struct m_Intrinsic_Ty;
+template <typename T0> struct m_Intrinsic_Ty<T0> {
+ typedef match_combine_and<IntrinsicID_match, Argument_match<T0>> Ty;
};
-template <typename T0, typename T1>
-struct m_Intrinsic_Ty<T0, T1> {
- typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty,
- Argument_match<T1> > Ty;
+template <typename T0, typename T1> struct m_Intrinsic_Ty<T0, T1> {
+ typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, Argument_match<T1>>
+ Ty;
};
template <typename T0, typename T1, typename T2>
struct m_Intrinsic_Ty<T0, T1, T2> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty,
- Argument_match<T2> > Ty;
+ Argument_match<T2>> Ty;
};
template <typename T0, typename T1, typename T2, typename T3>
struct m_Intrinsic_Ty<T0, T1, T2, T3> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty,
- Argument_match<T3> > Ty;
+ Argument_match<T3>> Ty;
};
-/// Match intrinsic calls like this:
-/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
-template <Intrinsic::ID IntrID>
-inline IntrinsicID_match
-m_Intrinsic() { return IntrinsicID_match(IntrID); }
+/// \brief Match intrinsic calls like this:
+/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
+template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() {
+ return IntrinsicID_match(IntrID);
+}
-template<Intrinsic::ID IntrID, typename T0>
-inline typename m_Intrinsic_Ty<T0>::Ty
-m_Intrinsic(const T0 &Op0) {
+template <Intrinsic::ID IntrID, typename T0>
+inline typename m_Intrinsic_Ty<T0>::Ty m_Intrinsic(const T0 &Op0) {
return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1>
-inline typename m_Intrinsic_Ty<T0, T1>::Ty
-m_Intrinsic(const T0 &Op0, const T1 &Op1) {
+template <Intrinsic::ID IntrID, typename T0, typename T1>
+inline typename m_Intrinsic_Ty<T0, T1>::Ty m_Intrinsic(const T0 &Op0,
+ const T1 &Op1) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2,
+ typename T3>
inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3));
}
-// Helper intrinsic matching specializations
-template<typename Opnd0>
-inline typename m_Intrinsic_Ty<Opnd0>::Ty
-m_BSwap(const Opnd0 &Op0) {
+// Helper intrinsic matching specializations.
+template <typename Opnd0>
+inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) {
return m_Intrinsic<Intrinsic::bswap>(Op0);
}
-template<typename Opnd0, typename Opnd1>
-inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty
-m_FMin(const Opnd0 &Op0, const Opnd1 &Op1) {
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
return m_Intrinsic<Intrinsic::minnum>(Op0, Op1);
}
-template<typename Opnd0, typename Opnd1>
-inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty
-m_FMax(const Opnd0 &Op0, const Opnd1 &Op1) {
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
return m_Intrinsic<Intrinsic::maxnum>(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 <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+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<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+ }
+ /// Number of additional arguments excluding those intended
+ /// for garbage collection.
+ int numTotalVMSArgs() {
+ return cast<ConstantInt>(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<arg_iterator> call_args() {
+ return iterator_range<arg_iterator>(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<arg_iterator> vm_state_args() {
+ return iterator_range<arg_iterator>(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<arg_iterator> gc_args() {
+ return iterator_range<arg_iterator>(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<GCRelocateOperands> 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<const Instruction, const Value,
+ ImmutableCallSite> {
+ typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
+ 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<Instruction, Value, CallSite> {
+ typedef StatepointBase<Instruction, Value, CallSite> 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<ExtractValueInst>(Token) ||
+ isa<InvokeInst>(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<ExtractValueInst>(token)) {
+ return cast<Instruction>(token);
+ }
+
+ // This relocate is on exceptional path of an invoke statepoint
+ const BasicBlock *invokeBB =
+ cast<Instruction>(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<ConstantInt>(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<ConstantInt>(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 <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+std::vector<GCRelocateOperands>
+ StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
+ getRelocates(ImmutableStatepoint &IS) {
+
+ std::vector<GCRelocateOperands> 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<InvokeInst>(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<ExtractValueInst>(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 T> class TypedTrackingMDRef {
+ TrackingMDRef Ref;
+
+public:
+ TypedTrackingMDRef() {}
+ explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(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<Metadata *>(MD)); }
+
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
+};
+
+typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
+typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
+
+// Expose the underlying metadata to casting.
+template <> struct simplify_type<TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &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<Type*> subtypes() const {
+ return makeArrayRef(subtype_begin(), subtype_end());
+ }
typedef std::reverse_iterator<subtype_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<const Value*> VisitedConstants;
+ DenseSet<const MDNode *> VisitedMetadata;
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> 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<User *, 1, unsigned> 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<UseListOrder> 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 <class>
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 <unsigned>
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<ValueName *, 1> 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 <typename UseT> // UseT == 'Use' or 'const Use'
class use_iterator_impl
- : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
- typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super;
-
+ : public std::iterator<std::forward_iterator_tag, UseT *> {
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 <typename UserTy> // UserTy == 'User' or 'const User'
class user_iterator_impl
- : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> {
- typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super;
-
+ : public std::iterator<std::forward_iterator_tag, UserTy *> {
use_iterator_impl<Use> 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<const_use_iterator>(use_begin(), use_end());
}
+ bool user_empty() const { return UseList == nullptr; }
+
typedef user_iterator_impl<User> user_iterator;
typedef user_iterator_impl<const User> 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<GlobalObject, Value> {
}
};
-template <> struct isa_impl<MDNode, Value> {
- 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<Value*> {
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<ValueHandleBase**, 2, HandleBaseKind> 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<Value*, 2> 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<AssertingVH<ValueTy> >;
#ifndef NDEBUG
- ValueTy *getValPtr() const {
- return static_cast<ValueTy*>(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<Value*>(V); }
+ ValueTy *getValPtr() const { return static_cast<ValueTy *>(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<typename T>
struct DenseMapInfo<AssertingVH<T> > {
- typedef DenseMapInfo<T*> PointerInfo;
static inline AssertingVH<T> getEmptyKey() {
- return AssertingVH<T>(PointerInfo::getEmptyKey());
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
+ return Res;
}
- static inline T* getTombstoneKey() {
- return AssertingVH<T>(PointerInfo::getTombstoneKey());
+ static inline AssertingVH<T> getTombstoneKey() {
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
+ return Res;
}
static unsigned getHashValue(const AssertingVH<T> &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
}
-#ifndef NDEBUG
static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
- // Avoid downcasting AssertingVH<T> to T*, as empty/tombstone keys may not
- // be properly aligned pointers to T*.
- return LHS.ValueHandleBase::getValPtr() == RHS.ValueHandleBase::getValPtr();
+ return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
+ RHS.getRawValPtr());
}
-#else
- static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
- return LHS == RHS;
- }
-#endif
};
template <typename T>
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 <iterator>
+#include <memory>
namespace llvm {
@@ -79,11 +81,13 @@ class ValueMap {
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
+ typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
typedef typename Config::ExtraData ExtraData;
MapT Map;
+ std::unique_ptr<MDMapT> 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<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> 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<Value*>(static_cast<const Value*>(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<KeySansPointerT>(getValPtr()); }
@@ -252,19 +269,18 @@ public:
template<typename KeyT, typename ValueT, typename Config>
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > {
typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH;
- typedef DenseMapInfo<KeyT> PointerInfo;
static inline VH getEmptyKey() {
- return VH(PointerInfo::getEmptyKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getEmptyKey());
}
static inline VH getTombstoneKey() {
- return VH(PointerInfo::getTombstoneKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getTombstoneKey());
}
static unsigned getHashValue(const VH &Val) {
- return PointerInfo::getHashValue(Val.Unwrap());
+ return DenseMapInfo<KeyT>::getHashValue(Val.Unwrap());
}
static unsigned getHashValue(const KeyT &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<KeyT>::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<StringRef> Libcalls,
std::vector<const char *> &MustPreserveList,
@@ -141,6 +155,7 @@ private:
typedef StringMap<uint8_t> StringSet;
void initialize();
+ void destroyMergedModule();
std::unique_ptr<LLVMContext> 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 <cstdlib>
@@ -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 <functional>
+#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<void(const DiagnosticInfo &)>
- DiagnosticHandlerFunction;
+public:
+ struct StructTypeKeyInfo {
+ struct KeyTy {
+ ArrayRef<Type *> ETypes;
+ bool IsPacked;
+ KeyTy(ArrayRef<Type *> 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<StructType *, StructTypeKeyInfo> NonOpaqueStructTypeSet;
+ typedef DenseSet<StructType *> 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<Type *> 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<StructType*, 32> 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<MCFragment> {
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<MCSectionData> {
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<MCFragment> 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<MCSymbolData> Symbols;
+ DenseSet<const MCSymbol *> 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<typename T> 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<MCSymbol*, BumpPtrAllocator&> 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 <map>
-#include <vector>
#include <string>
#include <utility>
+#include <vector>
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<MCOperand>::iterator iterator;
+ typedef SmallVectorImpl<MCOperand>::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<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); }
+ format_object<int64_t> formatImm(int64_t Value) const {
+ return PrintImmHex ? formatHex(Value) : formatDec(Value);
+ }
/// Utility functions to print decimal/hexadecimal values.
- format_object1<int64_t> formatDec(const int64_t Value) const;
- format_object1<int64_t> formatHex(const int64_t Value) const;
- format_object1<uint64_t> formatHex(const uint64_t Value) const;
+ format_object<int64_t> formatDec(int64_t Value) const;
+ format_object<int64_t> formatHex(int64_t Value) const;
+ format_object<uint64_t> 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<const MCSectionData*,
- std::vector<MachO::any_relocation_info> > 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<const MCSectionData *, std::vector<RelAndSymbol>> Relocations;
llvm::DenseMap<const MCSectionData*, unsigned> 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<unsigned,unsigned> 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<const MCSection *, const MCExpr *> 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<const MCSection *, const MCExpr *> MCSectionSubPair;
/// MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
/// FooTargetStreamer &ATS = static_cast<FooTargetStreamer &>(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<MCTargetStreamer> 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<MCDwarfFrameInfo> 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<SubtargetFeatureKV> ProcFeatures; // Processor feature list
ArrayRef<SubtargetFeatureKV> 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 <memory>
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 <string>
+
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<MCTargetOptions::AsmInstrumentation> AsmInstrumentation(
@@ -40,6 +40,11 @@ cl::opt<bool> ShowMCInst("asm-show-inst",
cl::desc("Emit internal instruction representation to "
"assembly file"));
+cl::opt<std::string>
+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<MemoryBufferRef> 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<int32_t>(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<ELFT>::getSymbolVersion(SymbolRef SymRef,
}
template <class ELFT>
+uint64_t ELFObjectFile<ELFT>::getSectionFlags(SectionRef Sec) const {
+ DataRefImpl DRI = Sec.getRawDataRefImpl();
+ return toELFShdrIter(DRI)->sh_flags;
+}
+
+template <class ELFT>
+uint32_t ELFObjectFile<ELFT>::getSectionType(SectionRef Sec) const {
+ DataRefImpl DRI = Sec.getRawDataRefImpl();
+ return toELFShdrIter(DRI)->sh_type;
+}
+
+template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
uint64_t &Result) const {
const Elf_Sym *ESym = getSymbol(Symb);
@@ -280,12 +309,16 @@ std::error_code ELFObjectFile<ELFT>::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<ELFT>::Elf_Shdr * Section = EF.getSection(ESym);
+ if (Section != nullptr)
+ Result += Section->sh_addr;
+ }
return object_error::success;
}
@@ -373,6 +406,9 @@ uint32_t ELFObjectFile<ELFT>::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<ELFT>::isSectionBSS(DataRefImpl Sec) const {
}
template <class ELFT>
-bool ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC;
-}
-
-template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
-bool ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec) const {
- return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS;
-}
-
-template <class ELFT>
-bool ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec) const {
- Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
- return !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR));
-}
-
-template <class ELFT>
bool ELFObjectFile<ELFT>::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<ELFType<TargetEndianness, MaxAlign, false>, 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 <endianness TargetEndianness, std::size_t MaxAlign>
@@ -321,9 +324,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, 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<ELFType<TargetEndianness, MaxAlign, false>, 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 <endianness TargetEndianness, std::size_t MaxAlign>
@@ -358,9 +367,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, 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<ELFType<TargetEndianness, MaxAlign, true>,
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<ELFType<TargetEndianness, MaxAlign, false>,
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<Symbol> Global;
std::vector<Symbol> 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<SectionOrType> 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<Relocation> 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::ELFYAML::Section>)
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<ELFYAML::ELF_REL> {
};
template <>
+struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> {
+ static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value);
+};
+
+template <>
struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};
@@ -215,6 +238,10 @@ struct MappingTraits<ELFYAML::Object> {
static void mapping(IO &IO, ELFYAML::Object &Object);
};
+template <> struct MappingTraits<ELFYAML::SectionOrType> {
+ static void mapping(IO &IO, ELFYAML::SectionOrType &sectionOrType);
+};
+
} // 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<IRObjectFile *>(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<Module> takeModule();
static inline bool classof(const Binary *v) {
return v->isIR();
@@ -61,8 +65,8 @@ public:
static ErrorOr<MemoryBufferRef>
findBitcodeInMemBuffer(MemoryBufferRef Object);
- static ErrorOr<std::unique_ptr<IRObjectFile>>
- createIRObjectFile(MemoryBufferRef Object, LLVMContext &Context);
+ static ErrorOr<std::unique_ptr<IRObjectFile>> 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<uint8_t> getDyldInfoRebaseOpcodes() const;
ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
ArrayRef<uint8_t> 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<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
- std::error_code getAsArchive(std::unique_ptr<Archive> &Result) const;
+ ErrorOr<std::unique_ptr<Archive>> 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<Arg*, 16> 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 <system_error>
@@ -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<unsigned, unsigned> startLoc() const {
return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
@@ -216,8 +237,10 @@ public:
ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
: Expressions(Expressions), CounterValues(CounterValues) {}
+ void setCounts(ArrayRef<uint64_t> 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<StringRef> Filenames,
- uint64_t ExecutionCount)
- : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
- ExecutionCount(ExecutionCount) {}
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> 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<std::unique_ptr<CoverageMapping>>
- 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 <iterator>
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<std::input_iterator_tag, CoverageMappingRecord> {
- 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<StringRef> &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<StringRef> &Filenames)
@@ -105,29 +110,27 @@ public:
/// \brief Reader for the raw coverage mapping data.
class RawCoverageMappingReader : public RawCoverageReader {
- StringRef FunctionName;
ArrayRef<StringRef> TranslationUnitFilenames;
std::vector<StringRef> &Filenames;
std::vector<CounterExpression> &Expressions;
std::vector<CounterMappingRegion> &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<StringRef> TranslationUnitFilenames,
std::vector<StringRef> &Filenames,
std::vector<CounterExpression> &Expressions,
std::vector<CounterMappingRegion> &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::ObjectFile> Object;
std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
size_t CurrentRecord;
@@ -167,40 +168,16 @@ private:
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> 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<MemoryBuffer> &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<std::unique_ptr<BinaryCoverageReader>>
+ create(std::unique_ptr<MemoryBuffer> &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 <iterator>
namespace llvm {
@@ -96,6 +95,9 @@ public:
/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
+
+ static ErrorOr<std::unique_ptr<InstrProfReader>>
+ create(std::unique_ptr<MemoryBuffer> Buffer);
};
/// Reader for the simple text based instrprof format.
@@ -115,9 +117,8 @@ private:
/// The current set of counter values.
std::vector<uint64_t> 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<MemoryBuffer> 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<MemoryBuffer> 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<MemoryBuffer> 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<IndexedInstrProfReader> &Result);
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::string Path);
+
+ static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ create(std::unique_ptr<MemoryBuffer> 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 <vector>
namespace llvm {
@@ -42,8 +42,13 @@ public:
std::error_code addFunctionCounts(StringRef FunctionName,
uint64_t FunctionHash,
ArrayRef<uint64_t> 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<MemoryBuffer> writeBuffer();
+
+private:
+ std::pair<uint64_t, uint64_t> 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 <system_error>
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<X, Y *>::ret_type cast(Y *Val) {
// accepted.
//
template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+cast_or_null(const Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+cast_or_null(Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
cast_or_null(Y *Val) {
if (!Val) return nullptr;
@@ -282,6 +302,20 @@ dyn_cast(Y *Val) {
// value is accepted.
//
template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type
+dyn_cast_or_null(const Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
+ !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
+dyn_cast_or_null(Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
dyn_cast_or_null(Y *Val) {
return (Val && isa<X>(Val)) ? cast<X>(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<const char*> &) {}
+ virtual void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
// 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<class Ty>
-struct initializer {
+template <class Ty> struct initializer {
const Ty &Init;
initializer(const Ty &Val) : Init(Val) {}
- template<class Opt>
- void apply(Opt &O) const { O.setInitialValue(Init); }
+ template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); }
};
-template<class Ty>
-initializer<Ty> init(const Ty &Val) {
+template <class Ty> initializer<Ty> init(const Ty &Val) {
return initializer<Ty>(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<class Ty>
-struct LocationClass {
+template <class Ty> struct LocationClass {
Ty &Loc;
LocationClass(Ty &L) : Loc(L) {}
- template<class Opt>
- void apply(Opt &O) const { O.setLocation(O, Loc); }
+ template <class Opt> void apply(Opt &O) const { O.setLocation(O, Loc); }
};
-template<class Ty>
-LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); }
+template <class Ty> LocationClass<Ty> location(Ty &L) {
+ return LocationClass<Ty>(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<class Opt>
- void apply(Opt &O) const { O.setCategory(Category); }
+ template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
};
-
//===----------------------------------------------------------------------===//
// OptionValue class
@@ -360,11 +359,11 @@ private:
virtual void anchor();
};
-template<class DataType> struct OptionValue;
+template <class DataType> struct OptionValue;
// The default value safely does nothing. Option value printing is only
// best-effort.
-template<class DataType, bool isClass>
+template <class DataType, bool isClass>
struct OptionValueBase : public GenericOptionValue {
// Temporary storage for argument passing.
typedef OptionValue<DataType> 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<class DT>
- void setValue(const DT& /*V*/) {}
+ template <class DT> 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 DataType>
-class OptionValueCopy : public GenericOptionValue {
+template <class DataType> 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<DataType> &VC =
- static_cast< const OptionValueCopy<DataType>& >(V);
- if (!VC.hasValue()) return false;
+ static_cast<const OptionValueCopy<DataType> &>(V);
+ if (!VC.hasValue())
+ return false;
return compare(VC.getValue());
}
};
// Non-class option values.
-template<class DataType>
+template <class DataType>
struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
typedef DataType WrapperType;
};
// Top-level option class.
-template<class DataType>
+template <class DataType>
struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::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<class DT>
- OptionValue<DataType> &operator=(const DT& V) {
+ template <class DT> OptionValue<DataType> &operator=(const DT &V) {
this->setValue(V);
return *this;
}
@@ -437,36 +434,33 @@ struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> {
// Other safe-to-copy-by-value common option types.
enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
-template<>
+template <>
struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
typedef cl::boolOrDefault WrapperType;
OptionValue() {}
- OptionValue(const cl::boolOrDefault& V) {
- this->setValue(V);
- }
- OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault& V) {
+ OptionValue(const cl::boolOrDefault &V) { this->setValue(V); }
+ OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault &V) {
setValue(V);
return *this;
}
+
private:
void anchor() override;
};
-template<>
-struct OptionValue<std::string> : OptionValueCopy<std::string> {
+template <> struct OptionValue<std::string> : OptionValueCopy<std::string> {
typedef StringRef WrapperType;
OptionValue() {}
- OptionValue(const std::string& V) {
- this->setValue(V);
- }
- OptionValue<std::string> &operator=(const std::string& V) {
+ OptionValue(const std::string &V) { this->setValue(V); }
+ OptionValue<std::string> &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<void*>(0))
+#define clEnumValEnd (reinterpret_cast<void *>(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 DataType>
-class ValuesClass {
+template <class DataType> 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<std::pair<const char *, std::pair<int, const char *> >,4> Values;
+ SmallVector<std::pair<const char *, std::pair<int, const char *>>, 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<DataType>(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<class Opt>
- void apply(Opt &O) const {
+ template <class Opt> 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 <class DataType>
ValuesClass<DataType> LLVM_END_WITH_NULL
values(const char *Arg, DataType Val, const char *Desc, ...) {
- va_list ValueArgs;
- va_start(ValueArgs, Desc);
- ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs);
- va_end(ValueArgs);
- return Vals;
+ va_list ValueArgs;
+ va_start(ValueArgs, Desc);
+ ValuesClass<DataType> 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<class AnyOptionValue>
+ template <class AnyOptionValue>
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<const char*> &OptionNames) {
+ void getExtraOptionNames(SmallVectorImpl<const char *> &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 DataType>
-class parser : public generic_parser_base {
+template <class DataType> 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<DataType> V;
};
SmallVector<OptionInfo, 8> 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<DataType>(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<t>
+class basic_parser_impl { // non-template implementation of basic_parser<t>
public:
+ basic_parser_impl(Option &O) {}
+
virtual ~basic_parser_impl() {}
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueRequired;
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &) {}
+ void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
- 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 DataType>
-class basic_parser : public basic_parser_impl {
+template <class DataType> class basic_parser : public basic_parser_impl {
public:
+ basic_parser(Option &O) : basic_parser_impl(O) {}
typedef DataType parser_data_type;
typedef OptionValue<DataType> OptVal;
};
@@ -745,18 +738,14 @@ public:
//--------------------------------------------------
// parser<bool>
//
-template<>
-class parser<bool> : public basic_parser<bool> {
- const char *ArgStr;
+template <> class parser<bool> : public basic_parser<bool> {
public:
+ parser(Option &O) : basic_parser(O) {}
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val);
- template <class Opt>
- 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<bool>);
//--------------------------------------------------
// parser<boolOrDefault>
-template<>
-class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
+template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
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<boolOrDefault>);
//--------------------------------------------------
// parser<int>
//
-template<>
-class parser<int> : public basic_parser<int> {
+template <> class parser<int> : public basic_parser<int> {
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<int>);
-
//--------------------------------------------------
// parser<unsigned>
//
-template<>
-class parser<unsigned> : public basic_parser<unsigned> {
+template <> class parser<unsigned> : public basic_parser<unsigned> {
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<unsigned>);
//--------------------------------------------------
// parser<unsigned long long>
//
-template<>
+template <>
class parser<unsigned long long> : public basic_parser<unsigned long long> {
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<unsigned long long>);
//--------------------------------------------------
// parser<double>
//
-template<>
-class parser<double> : public basic_parser<double> {
+template <> class parser<double> : public basic_parser<double> {
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<double>);
//--------------------------------------------------
// parser<float>
//
-template<>
-class parser<float> : public basic_parser<float> {
+template <> class parser<float> : public basic_parser<float> {
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<float>);
//--------------------------------------------------
// parser<std::string>
//
-template<>
-class parser<std::string> : public basic_parser<std::string> {
+template <> class parser<std::string> : public basic_parser<std::string> {
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<std::string>);
//--------------------------------------------------
// parser<char>
//
-template<>
-class parser<char> : public basic_parser<char> {
+template <> class parser<char> : public basic_parser<char> {
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<char>);
// parser to handle all the template nastiness.
// This overloaded function is selected by the generic parser.
-template<class ParserClass, class DT>
+template <class ParserClass, class DT>
void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V,
const OptionValue<DT> &Default, size_t GlobalWidth) {
OptionValue<DT> 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<class ParserDT, class ValDT>
-struct OptionDiffPrinter {
- void print(const Option &O, const parser<ParserDT> P, const ValDT &/*V*/,
- const OptionValue<ValDT> &/*Default*/, size_t GlobalWidth) {
+template <class ParserDT, class ValDT> struct OptionDiffPrinter {
+ void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/,
+ const OptionValue<ValDT> & /*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<class DT>
-struct OptionDiffPrinter<DT, DT> {
+template <class DT> struct OptionDiffPrinter<DT, DT> {
void print(const Option &O, const parser<DT> P, const DT &V,
const OptionValue<DT> &Default, size_t GlobalWidth) {
P.printOptionDiff(O, V, Default, GlobalWidth);
@@ -989,15 +984,14 @@ struct OptionDiffPrinter<DT, DT> {
// This overloaded function is selected by the basic parser, which may parse a
// different type than the option type.
-template<class ParserClass, class ValDT>
+template <class ParserClass, class ValDT>
void printOptionDiff(
- const Option &O,
- const basic_parser<typename ParserClass::parser_data_type> &P,
- const ValDT &V, const OptionValue<ValDT> &Default,
- size_t GlobalWidth) {
+ const Option &O,
+ const basic_parser<typename ParserClass::parser_data_type> &P,
+ const ValDT &V, const OptionValue<ValDT> &Default, size_t GlobalWidth) {
OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer;
- printer.print(O, static_cast<const ParserClass&>(P), V, Default,
+ printer.print(O, static_cast<const ParserClass &>(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<class Mod> struct applicator {
- template<class Opt>
- static void opt(const Mod &M, Opt &O) { M.apply(O); }
+template <class Mod> struct applicator {
+ template <class Opt> static void opt(const Mod &M, Opt &O) { M.apply(O); }
};
// Handle const char* as a special case...
-template<unsigned n> struct applicator<char[n]> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <unsigned n> struct applicator<char[n]> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<unsigned n> struct applicator<const char[n]> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <unsigned n> struct applicator<const char[n]> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<> struct applicator<const char*> {
- template<class Opt>
- static void opt(const char *Str, Opt &O) { O.setArgStr(Str); }
+template <> struct applicator<const char *> {
+ template <class Opt> static void opt(const char *Str, Opt &O) {
+ O.setArgStr(Str);
+ }
};
-template<> struct applicator<NumOccurrencesFlag> {
+template <> struct applicator<NumOccurrencesFlag> {
static void opt(NumOccurrencesFlag N, Option &O) {
O.setNumOccurrencesFlag(N);
}
};
-template<> struct applicator<ValueExpected> {
+template <> struct applicator<ValueExpected> {
static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); }
};
-template<> struct applicator<OptionHidden> {
+template <> struct applicator<OptionHidden> {
static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); }
};
-template<> struct applicator<FormattingFlags> {
+template <> struct applicator<FormattingFlags> {
static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); }
};
-template<> struct applicator<MiscFlags> {
+template <> struct applicator<MiscFlags> {
static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
};
-// apply method - Apply a modifier to an option in a type safe way.
-template<class Mod, class Opt>
-void apply(const Mod &M, Opt *O) {
+// apply method - Apply modifiers to an option in a type safe way.
+template <class Opt, class Mod, class... Mods>
+void apply(Opt *O, const Mod &M, const Mods &... Ms) {
+ applicator<Mod>::opt(M, *O);
+ apply(O, Ms...);
+}
+
+template <class Opt, class Mod> void apply(Opt *O, const Mod &M) {
applicator<Mod>::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<class DataType, bool ExternalStorage, bool isClass>
+template <class DataType, bool ExternalStorage, bool isClass>
class opt_storage {
- DataType *Location; // Where to store the object...
+ DataType *Location; // Where to store the object...
OptionValue<DataType> 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<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> 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 DataType>
-class opt_storage<DataType,false,true> : public DataType {
+template <class DataType>
+class opt_storage<DataType, false, true> : public DataType {
public:
OptionValue<DataType> Default;
- template<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> 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 DataType>
-class opt_storage<DataType, false, false> {
+template <class DataType> class opt_storage<DataType, false, false> {
public:
DataType Value;
OptionValue<DataType> Default;
@@ -1130,8 +1135,7 @@ public:
// type.
opt_storage() : Value(DataType()), Default(DataType()) {}
- template<class T>
- void setValue(const T &V, bool initial = false) {
+ template <class T> 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 DataType, bool ExternalStorage = false,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class opt : public Option,
public opt_storage<DataType, ExternalStorage,
std::is_class<DataType>::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<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &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<ParserClass>(
- *this, Parser, this->getValue(), this->getDefault(), GlobalWidth);
+ cl::printOptionDiff<ParserClass>(*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<class T>
- DataType &operator=(const T &Val) {
+ template <class T> DataType &operator=(const T &Val) {
this->setValue(Val);
return this->getValue();
}
- // One option...
- template<class M0t>
- explicit opt(const M0t &M0) : Option(Optional, NotHidden) {
- apply(M0, this);
- done();
- }
-
- // Two options...
- template<class M0t, class M1t>
- opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) {
- apply(M0, this); apply(M1, this);
- done();
- }
-
- // Three options...
- template<class M0t, class M1t, class M2t>
- 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<class M0t, class M1t, class M2t, class M3t>
- 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<class M0t, class M1t, class M2t, class M3t, class M4t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
- 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 <class... Mods>
+ explicit opt(const Mods &... Ms)
+ : Option(Optional, NotHidden), Parser(*this) {
+ apply(this, Ms...);
done();
}
};
@@ -1285,9 +1236,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>);
// assumes the user will specify a variable to store the data into with the
// cl::location(x) modifier.
//
-template<class DataType, class StorageClass>
-class list_storage {
- StorageClass *Location; // Where to store the object...
+template <class DataType, class StorageClass> class list_storage {
+ StorageClass *Location; // Where to store the object...
public:
list_storage() : Location(0) {}
@@ -1299,32 +1249,30 @@ public:
return false;
}
- template<class T>
- void addValue(const T &V) {
+ template <class T> 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<class DataType>
+template <class DataType>
class list_storage<DataType, bool> : public std::vector<DataType> {
public:
- template<class T>
- void addValue(const T &V) { std::vector<DataType>::push_back(V); }
+ template <class T> void addValue(const T &V) {
+ std::vector<DataType>::push_back(V);
+ }
};
-
//===----------------------------------------------------------------------===//
// list - A list of command line options.
//
template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class list : public Option, public list_storage<DataType, Storage> {
std::vector<unsigned> Positions;
ParserClass Parser;
@@ -1332,16 +1280,17 @@ class list : public Option, public list_storage<DataType, Storage> {
enum ValueExpected getValueExpectedFlagDefault() const override {
return Parser.getValueExpectedFlagDefault();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &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<DataType, Storage>::addValue(Val);
setPosition(pos);
Positions.push_back(pos);
@@ -1349,19 +1298,26 @@ class list : public Option, public list_storage<DataType, 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<class M0t>
- explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- done();
- }
- // Two options...
- template<class M0t, class M1t>
- list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this);
- done();
- }
- // Three options...
- template<class M0t, class M1t, class M2t>
- 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<class M0t, class M1t, class M2t, class M3t>
- 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<class M0t, class M1t, class M2t, class M3t, class M4t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
- 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 <class... Mods>
+ 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 <typename D, typename S, typename P>
- void apply(list<D, S, P> &L) const { L.setNumAdditionalVals(AdditionalVals); }
+ void apply(list<D, S, P> &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 DataType, class StorageClass>
-class bits_storage {
- unsigned *Location; // Where to store the bits...
+template <class DataType, class StorageClass> class bits_storage {
+ unsigned *Location; // Where to store the bits...
- template<class T>
- static unsigned Bit(const T &V) {
+ template <class T> static unsigned Bit(const T &V) {
unsigned BitPos = reinterpret_cast<unsigned>(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<class T>
- void addValue(const T &V) {
+ template <class T> 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<class T>
- bool isSet(const T &V) {
+ template <class T> 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 DataType>
-class bits_storage<DataType, bool> {
- unsigned Bits; // Where to store the bits...
+template <class DataType> class bits_storage<DataType, bool> {
+ unsigned Bits; // Where to store the bits...
- template<class T>
- static unsigned Bit(const T &V) {
+ template <class T> 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<class T>
- void addValue(const T &V) {
- Bits |= Bit(V);
- }
+ template <class T> void addValue(const T &V) { Bits |= Bit(V); }
unsigned getBits() { return Bits; }
- template<class T>
- bool isSet(const T &V) {
- return (Bits & Bit(V)) != 0;
- }
+ template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; }
};
-
//===----------------------------------------------------------------------===//
// bits - A bit vector of command options.
//
template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType> >
+ class ParserClass = parser<DataType>>
class bits : public Option, public bits_storage<DataType, Storage> {
std::vector<unsigned> Positions;
ParserClass Parser;
@@ -1536,16 +1420,17 @@ class bits : public Option, public bits_storage<DataType, Storage> {
enum ValueExpected getValueExpectedFlagDefault() const override {
return Parser.getValueExpectedFlagDefault();
}
- void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override {
+ void
+ getExtraOptionNames(SmallVectorImpl<const char *> &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<DataType, 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<class M0t>
- explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this);
- done();
- }
- // Two options...
- template<class M0t, class M1t>
- bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) {
- apply(M0, this); apply(M1, this);
- done();
- }
- // Three options...
- template<class M0t, class M1t, class M2t>
- 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<class M0t, class M1t, class M2t, class M3t>
- 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<class M0t, class M1t, class M2t, class M3t, class M4t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t>
- 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<class M0t, class M1t, class M2t, class M3t,
- class M4t, class M5t, class M6t, class M7t>
- 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 <class... Mods>
+ 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<class M0t>
- explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this);
- done();
- }
- // Two options...
- template<class M0t, class M1t>
- alias(const M0t &M0, const M1t &M1)
- : Option(Optional, Hidden), AliasFor(nullptr) {
- apply(M0, this); apply(M1, this);
- done();
- }
- // Three options...
- template<class M0t, class M1t, class M2t>
- 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<class M0t, class M1t, class M2t, class M3t>
- 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 <class... Mods>
+ 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<llvm::cl::Option*> opts;
-/// llvm::cl::getRegisteredOptions(opts);
+/// StringMap<llvm::cl::Option*> &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<Option*> &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<Option *> &getRegisteredOptions();
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
@@ -1776,9 +1595,10 @@ void getRegisteredOptions(StringMap<Option*> &Map);
/// raw character pointer.
class StringSaver {
virtual void anchor();
+
public:
virtual const char *SaveString(const char *Str) = 0;
- virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor.
+ virtual ~StringSaver(){}; // Pacify -Wnon-virtual-dtor.
};
/// \brief Tokenizes a command line that can contain escapes and quotes.
@@ -1836,6 +1656,24 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv,
bool MarkEOLs = false);
+/// \brief Mark all options not part of this category as cl::ReallyHidden.
+///
+/// \param Category the category of options to keep displaying
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(cl::OptionCategory &Category);
+
+/// \brief Mark all options not part of the categories as cl::ReallyHidden.
+///
+/// \param Categories the categories of options to keep displaying.
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
+
} // End namespace cl
} // End namespace llvm
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index d008fec..f7de840 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -52,14 +52,14 @@
/// \macro LLVM_MSC_PREREQ
/// \brief Is the compiler MSVC of at least the specified version?
/// The common \param version values to check for are:
-/// * 1700: Microsoft Visual Studio 2012 / 11.0
/// * 1800: Microsoft Visual Studio 2013 / 12.0
+/// * 1900: Microsoft Visual Studio 2015 / 14.0
#ifdef _MSC_VER
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
-// We require at least MSVC 2012.
-#if !LLVM_MSC_PREREQ(1700)
-#error LLVM requires at least MSVC 2012.
+// We require at least MSVC 2013.
+#if !LLVM_MSC_PREREQ(1800)
+#error LLVM requires at least MSVC 2013.
#endif
#else
@@ -82,16 +82,6 @@
#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
#endif
-/// \macro LLVM_HAS_VARIADIC_TEMPLATES
-/// \brief Does this compiler support variadic templates.
-///
-/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward.
-#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800)
-# define LLVM_HAS_VARIADIC_TEMPLATES 1
-#else
-# define LLVM_HAS_VARIADIC_TEMPLATES 0
-#endif
-
/// Expands to '&' if r-value references are supported.
///
/// This can be used to provide l-value/r-value overrides of member functions.
@@ -102,24 +92,6 @@
#define LLVM_LVALUE_FUNCTION
#endif
-/// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it.
-/// Use to mark functions as uncallable. Member functions with this should
-/// be declared private so that some behavior is kept in C++03 mode.
-///
-/// class DontCopy {
-/// private:
-/// DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION;
-/// DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION;
-/// public:
-/// ...
-/// };
-#if __has_feature(cxx_deleted_functions) || \
- defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800)
-#define LLVM_DELETED_FUNCTION = delete
-#else
-#define LLVM_DELETED_FUNCTION
-#endif
-
#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__)
# define LLVM_CONSTEXPR constexpr
#else
@@ -287,6 +259,12 @@
/// which causes the program to exit abnormally.
#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
# define LLVM_BUILTIN_TRAP __builtin_trap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+# define LLVM_BUILTIN_TRAP __debugbreak()
#else
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
#endif
@@ -344,26 +322,6 @@
# define LLVM_IS_UNALIGNED_ACCESS_FAST 0
#endif
-/// \macro LLVM_EXPLICIT
-/// \brief Expands to explicit on compilers which support explicit conversion
-/// operators. Otherwise expands to nothing.
-#if __has_feature(cxx_explicit_conversions) || \
- defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800)
-#define LLVM_EXPLICIT explicit
-#else
-#define LLVM_EXPLICIT
-#endif
-
-/// \brief Does the compiler support generalized initializers (using braced
-/// lists and std::initializer_list). While clang may claim it supports general
-/// initializers, if we're using MSVC's headers, we might not have a usable
-/// std::initializer list type from the STL. Disable this for now.
-#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER)
-#define LLVM_HAS_INITIALIZER_LISTS 1
-#else
-#define LLVM_HAS_INITIALIZER_LISTS 0
-#endif
-
/// \brief Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
// FIXME: Move this to a private config.h as it's not usable in public headers.
@@ -373,4 +331,33 @@
#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
#endif
+/// \macro LLVM_THREAD_LOCAL
+/// \brief A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support, and uses that when available. However, it falls back on
+/// platform-specific or vendor-provided extensions when necessary. These
+/// extensions don't support many of the C++11 thread_local's features. You
+/// should only use this for PODs that you can statically initialize to
+/// some constant value. In almost all circumstances this is most appropriate
+/// for use with a pointer, integer, or small aggregation of pointers and
+/// integers.
+#if LLVM_ENABLE_THREADS
+#if __has_feature(cxx_thread_local)
+#define LLVM_THREAD_LOCAL thread_local
+#elif defined(_MSC_VER)
+// MSVC supports this with a __declspec.
+#define LLVM_THREAD_LOCAL __declspec(thread)
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define LLVM_THREAD_LOCAL __thread
+#endif
+#else // !LLVM_ENABLE_THREADS
+// If threading is disabled entirely, this compiles to nothing and you get
+// a normal global variable.
+#define LLVM_THREAD_LOCAL
+#endif
+
#endif
diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h
index 8152b60..88727fa 100644
--- a/include/llvm/Support/Compression.h
+++ b/include/llvm/Support/Compression.h
@@ -14,9 +14,9 @@
#ifndef LLVM_SUPPORT_COMPRESSION_H
#define LLVM_SUPPORT_COMPRESSION_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include <memory>
-#include "llvm/ADT/SmallVector.h"
namespace llvm {
diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h
index a184d0d..38952ec 100644
--- a/include/llvm/Support/ConvertUTF.h
+++ b/include/llvm/Support/ConvertUTF.h
@@ -251,6 +251,14 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes);
*/
bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
+/**
+ * Converts a UTF-8 string into a UTF-16 string with native endianness.
+ *
+ * \returns true on success
+ */
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+ SmallVectorImpl<UTF16> &DstUTF16);
+
} /* end namespace llvm */
#endif
diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h
index f1e636d..1f3965c 100644
--- a/include/llvm/Support/CrashRecoveryContext.h
+++ b/include/llvm/Support/CrashRecoveryContext.h
@@ -10,9 +10,8 @@
#ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
#define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
-#include <string>
-
#include "llvm/ADT/STLExtras.h"
+#include <string>
namespace llvm {
class StringRef;
diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def
new file mode 100644
index 0000000..c663af9
--- /dev/null
+++ b/include/llvm/Support/Dwarf.def
@@ -0,0 +1,351 @@
+//===- llvm/Support/Dwarf.def - Dwarf 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 Dwarf enumerators.
+//
+//===----------------------------------------------------------------------===//
+
+// TODO: Add other DW-based macros.
+#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \
+ defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
+ defined HANDLE_DW_VIRTUALITY)
+#error "Missing macro definition of HANDLE_DW*"
+#endif
+
+#ifndef HANDLE_DW_TAG
+#define HANDLE_DW_TAG(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_OP
+#define HANDLE_DW_OP(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_LANG
+#define HANDLE_DW_LANG(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_ATE
+#define HANDLE_DW_ATE(ID, NAME)
+#endif
+
+#ifndef HANDLE_DW_VIRTUALITY
+#define HANDLE_DW_VIRTUALITY(ID, NAME)
+#endif
+
+HANDLE_DW_TAG(0x0001, array_type)
+HANDLE_DW_TAG(0x0002, class_type)
+HANDLE_DW_TAG(0x0003, entry_point)
+HANDLE_DW_TAG(0x0004, enumeration_type)
+HANDLE_DW_TAG(0x0005, formal_parameter)
+HANDLE_DW_TAG(0x0008, imported_declaration)
+HANDLE_DW_TAG(0x000a, label)
+HANDLE_DW_TAG(0x000b, lexical_block)
+HANDLE_DW_TAG(0x000d, member)
+HANDLE_DW_TAG(0x000f, pointer_type)
+HANDLE_DW_TAG(0x0010, reference_type)
+HANDLE_DW_TAG(0x0011, compile_unit)
+HANDLE_DW_TAG(0x0012, string_type)
+HANDLE_DW_TAG(0x0013, structure_type)
+HANDLE_DW_TAG(0x0015, subroutine_type)
+HANDLE_DW_TAG(0x0016, typedef)
+HANDLE_DW_TAG(0x0017, union_type)
+HANDLE_DW_TAG(0x0018, unspecified_parameters)
+HANDLE_DW_TAG(0x0019, variant)
+HANDLE_DW_TAG(0x001a, common_block)
+HANDLE_DW_TAG(0x001b, common_inclusion)
+HANDLE_DW_TAG(0x001c, inheritance)
+HANDLE_DW_TAG(0x001d, inlined_subroutine)
+HANDLE_DW_TAG(0x001e, module)
+HANDLE_DW_TAG(0x001f, ptr_to_member_type)
+HANDLE_DW_TAG(0x0020, set_type)
+HANDLE_DW_TAG(0x0021, subrange_type)
+HANDLE_DW_TAG(0x0022, with_stmt)
+HANDLE_DW_TAG(0x0023, access_declaration)
+HANDLE_DW_TAG(0x0024, base_type)
+HANDLE_DW_TAG(0x0025, catch_block)
+HANDLE_DW_TAG(0x0026, const_type)
+HANDLE_DW_TAG(0x0027, constant)
+HANDLE_DW_TAG(0x0028, enumerator)
+HANDLE_DW_TAG(0x0029, file_type)
+HANDLE_DW_TAG(0x002a, friend)
+HANDLE_DW_TAG(0x002b, namelist)
+HANDLE_DW_TAG(0x002c, namelist_item)
+HANDLE_DW_TAG(0x002d, packed_type)
+HANDLE_DW_TAG(0x002e, subprogram)
+HANDLE_DW_TAG(0x002f, template_type_parameter)
+HANDLE_DW_TAG(0x0030, template_value_parameter)
+HANDLE_DW_TAG(0x0031, thrown_type)
+HANDLE_DW_TAG(0x0032, try_block)
+HANDLE_DW_TAG(0x0033, variant_part)
+HANDLE_DW_TAG(0x0034, variable)
+HANDLE_DW_TAG(0x0035, volatile_type)
+HANDLE_DW_TAG(0x0036, dwarf_procedure)
+HANDLE_DW_TAG(0x0037, restrict_type)
+HANDLE_DW_TAG(0x0038, interface_type)
+HANDLE_DW_TAG(0x0039, namespace)
+HANDLE_DW_TAG(0x003a, imported_module)
+HANDLE_DW_TAG(0x003b, unspecified_type)
+HANDLE_DW_TAG(0x003c, partial_unit)
+HANDLE_DW_TAG(0x003d, imported_unit)
+HANDLE_DW_TAG(0x003f, condition)
+HANDLE_DW_TAG(0x0040, shared_type)
+HANDLE_DW_TAG(0x0041, type_unit)
+HANDLE_DW_TAG(0x0042, rvalue_reference_type)
+HANDLE_DW_TAG(0x0043, template_alias)
+
+// Mock tags we use as discriminators.
+HANDLE_DW_TAG(0x0100, auto_variable) // Tag for local (auto) variables.
+HANDLE_DW_TAG(0x0101, arg_variable) // Tag for argument variables.
+HANDLE_DW_TAG(0x0102, expression) // Tag for complex address expressions.
+
+// New in DWARF v5.
+HANDLE_DW_TAG(0x0044, coarray_type)
+HANDLE_DW_TAG(0x0045, generic_subrange)
+HANDLE_DW_TAG(0x0046, dynamic_type)
+
+// User-defined tags.
+HANDLE_DW_TAG(0x4081, MIPS_loop)
+HANDLE_DW_TAG(0x4101, format_label)
+HANDLE_DW_TAG(0x4102, function_template)
+HANDLE_DW_TAG(0x4103, class_template)
+HANDLE_DW_TAG(0x4106, GNU_template_template_param)
+HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack)
+HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack)
+HANDLE_DW_TAG(0x4200, APPLE_property)
+
+HANDLE_DW_OP(0x03, addr)
+HANDLE_DW_OP(0x06, deref)
+HANDLE_DW_OP(0x08, const1u)
+HANDLE_DW_OP(0x09, const1s)
+HANDLE_DW_OP(0x0a, const2u)
+HANDLE_DW_OP(0x0b, const2s)
+HANDLE_DW_OP(0x0c, const4u)
+HANDLE_DW_OP(0x0d, const4s)
+HANDLE_DW_OP(0x0e, const8u)
+HANDLE_DW_OP(0x0f, const8s)
+HANDLE_DW_OP(0x10, constu)
+HANDLE_DW_OP(0x11, consts)
+HANDLE_DW_OP(0x12, dup)
+HANDLE_DW_OP(0x13, drop)
+HANDLE_DW_OP(0x14, over)
+HANDLE_DW_OP(0x15, pick)
+HANDLE_DW_OP(0x16, swap)
+HANDLE_DW_OP(0x17, rot)
+HANDLE_DW_OP(0x18, xderef)
+HANDLE_DW_OP(0x19, abs)
+HANDLE_DW_OP(0x1a, and)
+HANDLE_DW_OP(0x1b, div)
+HANDLE_DW_OP(0x1c, minus)
+HANDLE_DW_OP(0x1d, mod)
+HANDLE_DW_OP(0x1e, mul)
+HANDLE_DW_OP(0x1f, neg)
+HANDLE_DW_OP(0x20, not)
+HANDLE_DW_OP(0x21, or )
+HANDLE_DW_OP(0x22, plus)
+HANDLE_DW_OP(0x23, plus_uconst)
+HANDLE_DW_OP(0x24, shl)
+HANDLE_DW_OP(0x25, shr)
+HANDLE_DW_OP(0x26, shra)
+HANDLE_DW_OP(0x27, xor)
+HANDLE_DW_OP(0x2f, skip)
+HANDLE_DW_OP(0x28, bra)
+HANDLE_DW_OP(0x29, eq)
+HANDLE_DW_OP(0x2a, ge)
+HANDLE_DW_OP(0x2b, gt)
+HANDLE_DW_OP(0x2c, le)
+HANDLE_DW_OP(0x2d, lt)
+HANDLE_DW_OP(0x2e, ne)
+HANDLE_DW_OP(0x30, lit0)
+HANDLE_DW_OP(0x31, lit1)
+HANDLE_DW_OP(0x32, lit2)
+HANDLE_DW_OP(0x33, lit3)
+HANDLE_DW_OP(0x34, lit4)
+HANDLE_DW_OP(0x35, lit5)
+HANDLE_DW_OP(0x36, lit6)
+HANDLE_DW_OP(0x37, lit7)
+HANDLE_DW_OP(0x38, lit8)
+HANDLE_DW_OP(0x39, lit9)
+HANDLE_DW_OP(0x3a, lit10)
+HANDLE_DW_OP(0x3b, lit11)
+HANDLE_DW_OP(0x3c, lit12)
+HANDLE_DW_OP(0x3d, lit13)
+HANDLE_DW_OP(0x3e, lit14)
+HANDLE_DW_OP(0x3f, lit15)
+HANDLE_DW_OP(0x40, lit16)
+HANDLE_DW_OP(0x41, lit17)
+HANDLE_DW_OP(0x42, lit18)
+HANDLE_DW_OP(0x43, lit19)
+HANDLE_DW_OP(0x44, lit20)
+HANDLE_DW_OP(0x45, lit21)
+HANDLE_DW_OP(0x46, lit22)
+HANDLE_DW_OP(0x47, lit23)
+HANDLE_DW_OP(0x48, lit24)
+HANDLE_DW_OP(0x49, lit25)
+HANDLE_DW_OP(0x4a, lit26)
+HANDLE_DW_OP(0x4b, lit27)
+HANDLE_DW_OP(0x4c, lit28)
+HANDLE_DW_OP(0x4d, lit29)
+HANDLE_DW_OP(0x4e, lit30)
+HANDLE_DW_OP(0x4f, lit31)
+HANDLE_DW_OP(0x50, reg0)
+HANDLE_DW_OP(0x51, reg1)
+HANDLE_DW_OP(0x52, reg2)
+HANDLE_DW_OP(0x53, reg3)
+HANDLE_DW_OP(0x54, reg4)
+HANDLE_DW_OP(0x55, reg5)
+HANDLE_DW_OP(0x56, reg6)
+HANDLE_DW_OP(0x57, reg7)
+HANDLE_DW_OP(0x58, reg8)
+HANDLE_DW_OP(0x59, reg9)
+HANDLE_DW_OP(0x5a, reg10)
+HANDLE_DW_OP(0x5b, reg11)
+HANDLE_DW_OP(0x5c, reg12)
+HANDLE_DW_OP(0x5d, reg13)
+HANDLE_DW_OP(0x5e, reg14)
+HANDLE_DW_OP(0x5f, reg15)
+HANDLE_DW_OP(0x60, reg16)
+HANDLE_DW_OP(0x61, reg17)
+HANDLE_DW_OP(0x62, reg18)
+HANDLE_DW_OP(0x63, reg19)
+HANDLE_DW_OP(0x64, reg20)
+HANDLE_DW_OP(0x65, reg21)
+HANDLE_DW_OP(0x66, reg22)
+HANDLE_DW_OP(0x67, reg23)
+HANDLE_DW_OP(0x68, reg24)
+HANDLE_DW_OP(0x69, reg25)
+HANDLE_DW_OP(0x6a, reg26)
+HANDLE_DW_OP(0x6b, reg27)
+HANDLE_DW_OP(0x6c, reg28)
+HANDLE_DW_OP(0x6d, reg29)
+HANDLE_DW_OP(0x6e, reg30)
+HANDLE_DW_OP(0x6f, reg31)
+HANDLE_DW_OP(0x70, breg0)
+HANDLE_DW_OP(0x71, breg1)
+HANDLE_DW_OP(0x72, breg2)
+HANDLE_DW_OP(0x73, breg3)
+HANDLE_DW_OP(0x74, breg4)
+HANDLE_DW_OP(0x75, breg5)
+HANDLE_DW_OP(0x76, breg6)
+HANDLE_DW_OP(0x77, breg7)
+HANDLE_DW_OP(0x78, breg8)
+HANDLE_DW_OP(0x79, breg9)
+HANDLE_DW_OP(0x7a, breg10)
+HANDLE_DW_OP(0x7b, breg11)
+HANDLE_DW_OP(0x7c, breg12)
+HANDLE_DW_OP(0x7d, breg13)
+HANDLE_DW_OP(0x7e, breg14)
+HANDLE_DW_OP(0x7f, breg15)
+HANDLE_DW_OP(0x80, breg16)
+HANDLE_DW_OP(0x81, breg17)
+HANDLE_DW_OP(0x82, breg18)
+HANDLE_DW_OP(0x83, breg19)
+HANDLE_DW_OP(0x84, breg20)
+HANDLE_DW_OP(0x85, breg21)
+HANDLE_DW_OP(0x86, breg22)
+HANDLE_DW_OP(0x87, breg23)
+HANDLE_DW_OP(0x88, breg24)
+HANDLE_DW_OP(0x89, breg25)
+HANDLE_DW_OP(0x8a, breg26)
+HANDLE_DW_OP(0x8b, breg27)
+HANDLE_DW_OP(0x8c, breg28)
+HANDLE_DW_OP(0x8d, breg29)
+HANDLE_DW_OP(0x8e, breg30)
+HANDLE_DW_OP(0x8f, breg31)
+HANDLE_DW_OP(0x90, regx)
+HANDLE_DW_OP(0x91, fbreg)
+HANDLE_DW_OP(0x92, bregx)
+HANDLE_DW_OP(0x93, piece)
+HANDLE_DW_OP(0x94, deref_size)
+HANDLE_DW_OP(0x95, xderef_size)
+HANDLE_DW_OP(0x96, nop)
+HANDLE_DW_OP(0x97, push_object_address)
+HANDLE_DW_OP(0x98, call2)
+HANDLE_DW_OP(0x99, call4)
+HANDLE_DW_OP(0x9a, call_ref)
+HANDLE_DW_OP(0x9b, form_tls_address)
+HANDLE_DW_OP(0x9c, call_frame_cfa)
+HANDLE_DW_OP(0x9d, bit_piece)
+HANDLE_DW_OP(0x9e, implicit_value)
+HANDLE_DW_OP(0x9f, stack_value)
+
+// Extensions for GNU-style thread-local storage.
+HANDLE_DW_OP(0xe0, GNU_push_tls_address)
+
+// Extensions for Fission proposal.
+HANDLE_DW_OP(0xfb, GNU_addr_index)
+HANDLE_DW_OP(0xfc, GNU_const_index)
+
+// DWARF languages.
+HANDLE_DW_LANG(0x0001, C89)
+HANDLE_DW_LANG(0x0002, C)
+HANDLE_DW_LANG(0x0003, Ada83)
+HANDLE_DW_LANG(0x0004, C_plus_plus)
+HANDLE_DW_LANG(0x0005, Cobol74)
+HANDLE_DW_LANG(0x0006, Cobol85)
+HANDLE_DW_LANG(0x0007, Fortran77)
+HANDLE_DW_LANG(0x0008, Fortran90)
+HANDLE_DW_LANG(0x0009, Pascal83)
+HANDLE_DW_LANG(0x000a, Modula2)
+HANDLE_DW_LANG(0x000b, Java)
+HANDLE_DW_LANG(0x000c, C99)
+HANDLE_DW_LANG(0x000d, Ada95)
+HANDLE_DW_LANG(0x000e, Fortran95)
+HANDLE_DW_LANG(0x000f, PLI)
+HANDLE_DW_LANG(0x0010, ObjC)
+HANDLE_DW_LANG(0x0011, ObjC_plus_plus)
+HANDLE_DW_LANG(0x0012, UPC)
+HANDLE_DW_LANG(0x0013, D)
+
+// New in DWARF 5:
+HANDLE_DW_LANG(0x0014, Python)
+HANDLE_DW_LANG(0x0015, OpenCL)
+HANDLE_DW_LANG(0x0016, Go)
+HANDLE_DW_LANG(0x0017, Modula3)
+HANDLE_DW_LANG(0x0018, Haskell)
+HANDLE_DW_LANG(0x0019, C_plus_plus_03)
+HANDLE_DW_LANG(0x001a, C_plus_plus_11)
+HANDLE_DW_LANG(0x001b, OCaml)
+HANDLE_DW_LANG(0x001c, Rust)
+HANDLE_DW_LANG(0x001d, C11)
+HANDLE_DW_LANG(0x001e, Swift)
+HANDLE_DW_LANG(0x001f, Julia)
+HANDLE_DW_LANG(0x0020, Dylan)
+HANDLE_DW_LANG(0x0021, C_plus_plus_14)
+HANDLE_DW_LANG(0x0022, Fortran03)
+HANDLE_DW_LANG(0x0023, Fortran08)
+HANDLE_DW_LANG(0x8001, Mips_Assembler)
+
+// DWARF attribute type encodings.
+HANDLE_DW_ATE(0x01, address)
+HANDLE_DW_ATE(0x02, boolean)
+HANDLE_DW_ATE(0x03, complex_float)
+HANDLE_DW_ATE(0x04, float)
+HANDLE_DW_ATE(0x05, signed)
+HANDLE_DW_ATE(0x06, signed_char)
+HANDLE_DW_ATE(0x07, unsigned)
+HANDLE_DW_ATE(0x08, unsigned_char)
+HANDLE_DW_ATE(0x09, imaginary_float)
+HANDLE_DW_ATE(0x0a, packed_decimal)
+HANDLE_DW_ATE(0x0b, numeric_string)
+HANDLE_DW_ATE(0x0c, edited)
+HANDLE_DW_ATE(0x0d, signed_fixed)
+HANDLE_DW_ATE(0x0e, unsigned_fixed)
+HANDLE_DW_ATE(0x0f, decimal_float)
+HANDLE_DW_ATE(0x10, UTF)
+
+// DWARF virtuality codes.
+HANDLE_DW_VIRTUALITY(0x00, none)
+HANDLE_DW_VIRTUALITY(0x01, virtual)
+HANDLE_DW_VIRTUALITY(0x02, pure_virtual)
+
+#undef HANDLE_DW_TAG
+#undef HANDLE_DW_OP
+#undef HANDLE_DW_LANG
+#undef HANDLE_DW_ATE
+#undef HANDLE_DW_VIRTUALITY
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index 47b00b1..c294a72 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -20,6 +20,7 @@
#ifndef LLVM_SUPPORT_DWARF_H
#define LLVM_SUPPORT_DWARF_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
@@ -36,15 +37,11 @@ namespace dwarf {
// enumeration base type.
enum LLVMConstants : uint32_t {
- // llvm mock tags
- DW_TAG_invalid = ~0U, // Tag for invalid results.
-
- DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables.
- DW_TAG_arg_variable = 0x101, // Tag for argument variables.
- DW_TAG_expression = 0x102, // Tag for complex address expressions.
-
- DW_TAG_user_base = 0x1000, // Recommended base for user tags.
+ // LLVM mock tags (see also llvm/Support/Dwarf.def).
+ DW_TAG_invalid = ~0U, // Tag for invalid results.
+ DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results.
+ // Other constants.
DWARF_VERSION = 4, // Default dwarf version we output.
DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes.
DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames.
@@ -57,82 +54,11 @@ const uint32_t DW_CIE_ID = UINT32_MAX;
const uint64_t DW64_CIE_ID = UINT64_MAX;
enum Tag : uint16_t {
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_parameter = 0x2f,
- DW_TAG_template_value_parameter = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- DW_TAG_type_unit = 0x41,
- DW_TAG_rvalue_reference_type = 0x42,
- DW_TAG_template_alias = 0x43,
-
- // New in DWARF 5:
- DW_TAG_coarray_type = 0x44,
- DW_TAG_generic_subrange = 0x45,
- DW_TAG_dynamic_type = 0x46,
-
- DW_TAG_MIPS_loop = 0x4081,
- DW_TAG_format_label = 0x4101,
- DW_TAG_function_template = 0x4102,
- DW_TAG_class_template = 0x4103,
- DW_TAG_GNU_template_template_param = 0x4106,
- DW_TAG_GNU_template_parameter_pack = 0x4107,
- DW_TAG_GNU_formal_parameter_pack = 0x4108,
+#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_TAG_lo_user = 0x4080,
- DW_TAG_APPLE_property = 0x4200,
- DW_TAG_hi_user = 0xffff
+ DW_TAG_hi_user = 0xffff,
+ DW_TAG_user_base = 0x1000 // Recommended base for user tags.
};
inline bool isType(Tag T) {
@@ -363,190 +289,15 @@ enum Form : uint16_t {
};
enum LocationAtom {
- // Operation encodings
- DW_OP_addr = 0x03,
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08,
- DW_OP_const1s = 0x09,
- DW_OP_const2u = 0x0a,
- DW_OP_const2s = 0x0b,
- DW_OP_const4u = 0x0c,
- DW_OP_const4s = 0x0d,
- DW_OP_const8u = 0x0e,
- DW_OP_const8s = 0x0f,
- DW_OP_constu = 0x10,
- DW_OP_consts = 0x11,
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15,
- DW_OP_swap = 0x16,
- DW_OP_rot = 0x17,
- DW_OP_xderef = 0x18,
- DW_OP_abs = 0x19,
- DW_OP_and = 0x1a,
- DW_OP_div = 0x1b,
- DW_OP_minus = 0x1c,
- DW_OP_mod = 0x1d,
- DW_OP_mul = 0x1e,
- DW_OP_neg = 0x1f,
- DW_OP_not = 0x20,
- DW_OP_or = 0x21,
- DW_OP_plus = 0x22,
- DW_OP_plus_uconst = 0x23,
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_skip = 0x2f,
- DW_OP_bra = 0x28,
- DW_OP_eq = 0x29,
- DW_OP_ge = 0x2a,
- DW_OP_gt = 0x2b,
- DW_OP_le = 0x2c,
- DW_OP_lt = 0x2d,
- DW_OP_ne = 0x2e,
- DW_OP_lit0 = 0x30,
- DW_OP_lit1 = 0x31,
- DW_OP_lit2 = 0x32,
- DW_OP_lit3 = 0x33,
- DW_OP_lit4 = 0x34,
- DW_OP_lit5 = 0x35,
- DW_OP_lit6 = 0x36,
- DW_OP_lit7 = 0x37,
- DW_OP_lit8 = 0x38,
- DW_OP_lit9 = 0x39,
- DW_OP_lit10 = 0x3a,
- DW_OP_lit11 = 0x3b,
- DW_OP_lit12 = 0x3c,
- DW_OP_lit13 = 0x3d,
- DW_OP_lit14 = 0x3e,
- DW_OP_lit15 = 0x3f,
- DW_OP_lit16 = 0x40,
- DW_OP_lit17 = 0x41,
- DW_OP_lit18 = 0x42,
- DW_OP_lit19 = 0x43,
- DW_OP_lit20 = 0x44,
- DW_OP_lit21 = 0x45,
- DW_OP_lit22 = 0x46,
- DW_OP_lit23 = 0x47,
- DW_OP_lit24 = 0x48,
- DW_OP_lit25 = 0x49,
- DW_OP_lit26 = 0x4a,
- DW_OP_lit27 = 0x4b,
- DW_OP_lit28 = 0x4c,
- DW_OP_lit29 = 0x4d,
- DW_OP_lit30 = 0x4e,
- DW_OP_lit31 = 0x4f,
- DW_OP_reg0 = 0x50,
- DW_OP_reg1 = 0x51,
- DW_OP_reg2 = 0x52,
- DW_OP_reg3 = 0x53,
- DW_OP_reg4 = 0x54,
- DW_OP_reg5 = 0x55,
- DW_OP_reg6 = 0x56,
- DW_OP_reg7 = 0x57,
- DW_OP_reg8 = 0x58,
- DW_OP_reg9 = 0x59,
- DW_OP_reg10 = 0x5a,
- DW_OP_reg11 = 0x5b,
- DW_OP_reg12 = 0x5c,
- DW_OP_reg13 = 0x5d,
- DW_OP_reg14 = 0x5e,
- DW_OP_reg15 = 0x5f,
- DW_OP_reg16 = 0x60,
- DW_OP_reg17 = 0x61,
- DW_OP_reg18 = 0x62,
- DW_OP_reg19 = 0x63,
- DW_OP_reg20 = 0x64,
- DW_OP_reg21 = 0x65,
- DW_OP_reg22 = 0x66,
- DW_OP_reg23 = 0x67,
- DW_OP_reg24 = 0x68,
- DW_OP_reg25 = 0x69,
- DW_OP_reg26 = 0x6a,
- DW_OP_reg27 = 0x6b,
- DW_OP_reg28 = 0x6c,
- DW_OP_reg29 = 0x6d,
- DW_OP_reg30 = 0x6e,
- DW_OP_reg31 = 0x6f,
- DW_OP_breg0 = 0x70,
- DW_OP_breg1 = 0x71,
- DW_OP_breg2 = 0x72,
- DW_OP_breg3 = 0x73,
- DW_OP_breg4 = 0x74,
- DW_OP_breg5 = 0x75,
- DW_OP_breg6 = 0x76,
- DW_OP_breg7 = 0x77,
- DW_OP_breg8 = 0x78,
- DW_OP_breg9 = 0x79,
- DW_OP_breg10 = 0x7a,
- DW_OP_breg11 = 0x7b,
- DW_OP_breg12 = 0x7c,
- DW_OP_breg13 = 0x7d,
- DW_OP_breg14 = 0x7e,
- DW_OP_breg15 = 0x7f,
- DW_OP_breg16 = 0x80,
- DW_OP_breg17 = 0x81,
- DW_OP_breg18 = 0x82,
- DW_OP_breg19 = 0x83,
- DW_OP_breg20 = 0x84,
- DW_OP_breg21 = 0x85,
- DW_OP_breg22 = 0x86,
- DW_OP_breg23 = 0x87,
- DW_OP_breg24 = 0x88,
- DW_OP_breg25 = 0x89,
- DW_OP_breg26 = 0x8a,
- DW_OP_breg27 = 0x8b,
- DW_OP_breg28 = 0x8c,
- DW_OP_breg29 = 0x8d,
- DW_OP_breg30 = 0x8e,
- DW_OP_breg31 = 0x8f,
- DW_OP_regx = 0x90,
- DW_OP_fbreg = 0x91,
- DW_OP_bregx = 0x92,
- DW_OP_piece = 0x93,
- DW_OP_deref_size = 0x94,
- DW_OP_xderef_size = 0x95,
- DW_OP_nop = 0x96,
- DW_OP_push_object_address = 0x97,
- DW_OP_call2 = 0x98,
- DW_OP_call4 = 0x99,
- DW_OP_call_ref = 0x9a,
- DW_OP_form_tls_address = 0x9b,
- DW_OP_call_frame_cfa = 0x9c,
- DW_OP_bit_piece = 0x9d,
- DW_OP_implicit_value = 0x9e,
- DW_OP_stack_value = 0x9f,
+#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_OP_lo_user = 0xe0,
- DW_OP_hi_user = 0xff,
-
- // Extensions for GNU-style thread-local storage.
- DW_OP_GNU_push_tls_address = 0xe0,
-
- // Extensions for Fission proposal.
- DW_OP_GNU_addr_index = 0xfb,
- DW_OP_GNU_const_index = 0xfc
+ DW_OP_hi_user = 0xff
};
enum TypeKind {
- // Encoding attribute values
- DW_ATE_address = 0x01,
- DW_ATE_boolean = 0x02,
- DW_ATE_complex_float = 0x03,
- DW_ATE_float = 0x04,
- DW_ATE_signed = 0x05,
- DW_ATE_signed_char = 0x06,
- DW_ATE_unsigned = 0x07,
- DW_ATE_unsigned_char = 0x08,
- DW_ATE_imaginary_float = 0x09,
- DW_ATE_packed_decimal = 0x0a,
- DW_ATE_numeric_string = 0x0b,
- DW_ATE_edited = 0x0c,
- DW_ATE_signed_fixed = 0x0d,
- DW_ATE_unsigned_fixed = 0x0e,
- DW_ATE_decimal_float = 0x0f,
- DW_ATE_UTF = 0x10,
+#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_ATE_lo_user = 0x80,
DW_ATE_hi_user = 0xff
};
@@ -584,45 +335,15 @@ enum VisibilityAttribute {
};
enum VirtualityAttribute {
- // Virtuality codes
- DW_VIRTUALITY_none = 0x00,
- DW_VIRTUALITY_virtual = 0x01,
- DW_VIRTUALITY_pure_virtual = 0x02
+#define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
+ DW_VIRTUALITY_max = 0x02
};
enum SourceLanguage {
- // Language names
- DW_LANG_C89 = 0x0001,
- DW_LANG_C = 0x0002,
- DW_LANG_Ada83 = 0x0003,
- DW_LANG_C_plus_plus = 0x0004,
- DW_LANG_Cobol74 = 0x0005,
- DW_LANG_Cobol85 = 0x0006,
- DW_LANG_Fortran77 = 0x0007,
- DW_LANG_Fortran90 = 0x0008,
- DW_LANG_Pascal83 = 0x0009,
- DW_LANG_Modula2 = 0x000a,
- DW_LANG_Java = 0x000b,
- DW_LANG_C99 = 0x000c,
- DW_LANG_Ada95 = 0x000d,
- DW_LANG_Fortran95 = 0x000e,
- DW_LANG_PLI = 0x000f,
- DW_LANG_ObjC = 0x0010,
- DW_LANG_ObjC_plus_plus = 0x0011,
- DW_LANG_UPC = 0x0012,
- DW_LANG_D = 0x0013,
- // New in DWARF 5:
- DW_LANG_Python = 0x0014,
- DW_LANG_OpenCL = 0x0015,
- DW_LANG_Go = 0x0016,
- DW_LANG_Modula3 = 0x0017,
- DW_LANG_Haskell = 0x0018,
- DW_LANG_C_plus_plus_03 = 0x0019,
- DW_LANG_C_plus_plus_11 = 0x001a,
- DW_LANG_OCaml = 0x001b,
-
+#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
DW_LANG_lo_user = 0x8000,
- DW_LANG_Mips_Assembler = 0x8001,
DW_LANG_hi_user = 0xffff
};
@@ -859,6 +580,22 @@ const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind);
const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
/// @}
+/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions
+///
+/// These functions map their strings back to the corresponding enumeration
+/// value or return 0 if there is none, except for these exceptions:
+///
+/// \li \a getTag() returns \a DW_TAG_invalid on invalid input.
+/// \li \a getVirtuality() returns \a DW_VIRTUALITY_invalid on invalid input.
+///
+/// @{
+unsigned getTag(StringRef TagString);
+unsigned getOperationEncoding(StringRef OperationEncodingString);
+unsigned getVirtuality(StringRef VirtualityString);
+unsigned getLanguage(StringRef LanguageString);
+unsigned getAttributeEncoding(StringRef EncodingString);
+/// @}
+
/// \brief Returns the symbolic string representing Val when used as a value
/// for attribute Attr.
const char *AttributeValueString(uint16_t Attr, unsigned Val);
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index 5f78cc2..fc6f314 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -350,152 +350,21 @@ enum {
ELFOSABI_STANDALONE = 255 // Standalone (embedded) application
};
+#define ELF_RELOC(name, value) name = value,
+
// X86_64 relocations.
enum {
- R_X86_64_NONE = 0,
- R_X86_64_64 = 1,
- R_X86_64_PC32 = 2,
- R_X86_64_GOT32 = 3,
- R_X86_64_PLT32 = 4,
- R_X86_64_COPY = 5,
- R_X86_64_GLOB_DAT = 6,
- R_X86_64_JUMP_SLOT = 7,
- R_X86_64_RELATIVE = 8,
- R_X86_64_GOTPCREL = 9,
- R_X86_64_32 = 10,
- R_X86_64_32S = 11,
- R_X86_64_16 = 12,
- R_X86_64_PC16 = 13,
- R_X86_64_8 = 14,
- R_X86_64_PC8 = 15,
- R_X86_64_DTPMOD64 = 16,
- R_X86_64_DTPOFF64 = 17,
- R_X86_64_TPOFF64 = 18,
- R_X86_64_TLSGD = 19,
- R_X86_64_TLSLD = 20,
- R_X86_64_DTPOFF32 = 21,
- R_X86_64_GOTTPOFF = 22,
- R_X86_64_TPOFF32 = 23,
- R_X86_64_PC64 = 24,
- R_X86_64_GOTOFF64 = 25,
- R_X86_64_GOTPC32 = 26,
- R_X86_64_GOT64 = 27,
- R_X86_64_GOTPCREL64 = 28,
- R_X86_64_GOTPC64 = 29,
- R_X86_64_GOTPLT64 = 30,
- R_X86_64_PLTOFF64 = 31,
- R_X86_64_SIZE32 = 32,
- R_X86_64_SIZE64 = 33,
- R_X86_64_GOTPC32_TLSDESC = 34,
- R_X86_64_TLSDESC_CALL = 35,
- R_X86_64_TLSDESC = 36,
- R_X86_64_IRELATIVE = 37
+#include "ELFRelocs/x86_64.def"
};
// i386 relocations.
-// TODO: this is just a subset
enum {
- R_386_NONE = 0,
- R_386_32 = 1,
- R_386_PC32 = 2,
- R_386_GOT32 = 3,
- R_386_PLT32 = 4,
- R_386_COPY = 5,
- R_386_GLOB_DAT = 6,
- R_386_JUMP_SLOT = 7,
- R_386_RELATIVE = 8,
- R_386_GOTOFF = 9,
- R_386_GOTPC = 10,
- R_386_32PLT = 11,
- R_386_TLS_TPOFF = 14,
- R_386_TLS_IE = 15,
- R_386_TLS_GOTIE = 16,
- R_386_TLS_LE = 17,
- R_386_TLS_GD = 18,
- R_386_TLS_LDM = 19,
- R_386_16 = 20,
- R_386_PC16 = 21,
- R_386_8 = 22,
- R_386_PC8 = 23,
- R_386_TLS_GD_32 = 24,
- R_386_TLS_GD_PUSH = 25,
- R_386_TLS_GD_CALL = 26,
- R_386_TLS_GD_POP = 27,
- R_386_TLS_LDM_32 = 28,
- R_386_TLS_LDM_PUSH = 29,
- R_386_TLS_LDM_CALL = 30,
- R_386_TLS_LDM_POP = 31,
- R_386_TLS_LDO_32 = 32,
- R_386_TLS_IE_32 = 33,
- R_386_TLS_LE_32 = 34,
- R_386_TLS_DTPMOD32 = 35,
- R_386_TLS_DTPOFF32 = 36,
- R_386_TLS_TPOFF32 = 37,
- R_386_TLS_GOTDESC = 39,
- R_386_TLS_DESC_CALL = 40,
- R_386_TLS_DESC = 41,
- R_386_IRELATIVE = 42,
- R_386_NUM = 43
+#include "ELFRelocs/i386.def"
};
// ELF Relocation types for PPC32
enum {
- R_PPC_NONE = 0, /* No relocation. */
- R_PPC_ADDR32 = 1,
- R_PPC_ADDR24 = 2,
- R_PPC_ADDR16 = 3,
- R_PPC_ADDR16_LO = 4,
- R_PPC_ADDR16_HI = 5,
- R_PPC_ADDR16_HA = 6,
- R_PPC_ADDR14 = 7,
- R_PPC_ADDR14_BRTAKEN = 8,
- R_PPC_ADDR14_BRNTAKEN = 9,
- R_PPC_REL24 = 10,
- R_PPC_REL14 = 11,
- R_PPC_REL14_BRTAKEN = 12,
- R_PPC_REL14_BRNTAKEN = 13,
- R_PPC_GOT16 = 14,
- R_PPC_GOT16_LO = 15,
- R_PPC_GOT16_HI = 16,
- R_PPC_GOT16_HA = 17,
- R_PPC_PLTREL24 = 18,
- R_PPC_JMP_SLOT = 21,
- R_PPC_LOCAL24PC = 23,
- R_PPC_REL32 = 26,
- R_PPC_TLS = 67,
- R_PPC_DTPMOD32 = 68,
- R_PPC_TPREL16 = 69,
- R_PPC_TPREL16_LO = 70,
- R_PPC_TPREL16_HI = 71,
- R_PPC_TPREL16_HA = 72,
- R_PPC_TPREL32 = 73,
- R_PPC_DTPREL16 = 74,
- R_PPC_DTPREL16_LO = 75,
- R_PPC_DTPREL16_HI = 76,
- R_PPC_DTPREL16_HA = 77,
- R_PPC_DTPREL32 = 78,
- R_PPC_GOT_TLSGD16 = 79,
- R_PPC_GOT_TLSGD16_LO = 80,
- R_PPC_GOT_TLSGD16_HI = 81,
- R_PPC_GOT_TLSGD16_HA = 82,
- R_PPC_GOT_TLSLD16 = 83,
- R_PPC_GOT_TLSLD16_LO = 84,
- R_PPC_GOT_TLSLD16_HI = 85,
- R_PPC_GOT_TLSLD16_HA = 86,
- R_PPC_GOT_TPREL16 = 87,
- R_PPC_GOT_TPREL16_LO = 88,
- R_PPC_GOT_TPREL16_HI = 89,
- R_PPC_GOT_TPREL16_HA = 90,
- R_PPC_GOT_DTPREL16 = 91,
- R_PPC_GOT_DTPREL16_LO = 92,
- R_PPC_GOT_DTPREL16_HI = 93,
- R_PPC_GOT_DTPREL16_HA = 94,
- R_PPC_TLSGD = 95,
- R_PPC_TLSLD = 96,
- R_PPC_REL16 = 249,
- R_PPC_REL16_LO = 250,
- R_PPC_REL16_HI = 251,
- R_PPC_REL16_HA = 252
+#include "ELFRelocs/PowerPC.def"
};
// Specific e_flags for PPC64
@@ -531,192 +400,12 @@ encodePPC64LocalEntryOffset(int64_t Offset) {
// ELF Relocation types for PPC64
enum {
- R_PPC64_NONE = 0,
- R_PPC64_ADDR32 = 1,
- R_PPC64_ADDR24 = 2,
- R_PPC64_ADDR16 = 3,
- R_PPC64_ADDR16_LO = 4,
- R_PPC64_ADDR16_HI = 5,
- R_PPC64_ADDR16_HA = 6,
- R_PPC64_ADDR14 = 7,
- R_PPC64_ADDR14_BRTAKEN = 8,
- R_PPC64_ADDR14_BRNTAKEN = 9,
- R_PPC64_REL24 = 10,
- R_PPC64_REL14 = 11,
- R_PPC64_REL14_BRTAKEN = 12,
- R_PPC64_REL14_BRNTAKEN = 13,
- R_PPC64_GOT16 = 14,
- R_PPC64_GOT16_LO = 15,
- R_PPC64_GOT16_HI = 16,
- R_PPC64_GOT16_HA = 17,
- R_PPC64_JMP_SLOT = 21,
- R_PPC64_REL32 = 26,
- R_PPC64_ADDR64 = 38,
- R_PPC64_ADDR16_HIGHER = 39,
- R_PPC64_ADDR16_HIGHERA = 40,
- R_PPC64_ADDR16_HIGHEST = 41,
- R_PPC64_ADDR16_HIGHESTA = 42,
- R_PPC64_REL64 = 44,
- R_PPC64_TOC16 = 47,
- R_PPC64_TOC16_LO = 48,
- R_PPC64_TOC16_HI = 49,
- R_PPC64_TOC16_HA = 50,
- R_PPC64_TOC = 51,
- R_PPC64_ADDR16_DS = 56,
- R_PPC64_ADDR16_LO_DS = 57,
- R_PPC64_GOT16_DS = 58,
- R_PPC64_GOT16_LO_DS = 59,
- R_PPC64_TOC16_DS = 63,
- R_PPC64_TOC16_LO_DS = 64,
- R_PPC64_TLS = 67,
- R_PPC64_DTPMOD64 = 68,
- R_PPC64_TPREL16 = 69,
- R_PPC64_TPREL16_LO = 70,
- R_PPC64_TPREL16_HI = 71,
- R_PPC64_TPREL16_HA = 72,
- R_PPC64_TPREL64 = 73,
- R_PPC64_DTPREL16 = 74,
- R_PPC64_DTPREL16_LO = 75,
- R_PPC64_DTPREL16_HI = 76,
- R_PPC64_DTPREL16_HA = 77,
- R_PPC64_DTPREL64 = 78,
- R_PPC64_GOT_TLSGD16 = 79,
- R_PPC64_GOT_TLSGD16_LO = 80,
- R_PPC64_GOT_TLSGD16_HI = 81,
- R_PPC64_GOT_TLSGD16_HA = 82,
- R_PPC64_GOT_TLSLD16 = 83,
- R_PPC64_GOT_TLSLD16_LO = 84,
- R_PPC64_GOT_TLSLD16_HI = 85,
- R_PPC64_GOT_TLSLD16_HA = 86,
- R_PPC64_GOT_TPREL16_DS = 87,
- R_PPC64_GOT_TPREL16_LO_DS = 88,
- R_PPC64_GOT_TPREL16_HI = 89,
- R_PPC64_GOT_TPREL16_HA = 90,
- R_PPC64_GOT_DTPREL16_DS = 91,
- R_PPC64_GOT_DTPREL16_LO_DS = 92,
- R_PPC64_GOT_DTPREL16_HI = 93,
- R_PPC64_GOT_DTPREL16_HA = 94,
- R_PPC64_TPREL16_DS = 95,
- R_PPC64_TPREL16_LO_DS = 96,
- R_PPC64_TPREL16_HIGHER = 97,
- R_PPC64_TPREL16_HIGHERA = 98,
- R_PPC64_TPREL16_HIGHEST = 99,
- R_PPC64_TPREL16_HIGHESTA = 100,
- R_PPC64_DTPREL16_DS = 101,
- R_PPC64_DTPREL16_LO_DS = 102,
- R_PPC64_DTPREL16_HIGHER = 103,
- R_PPC64_DTPREL16_HIGHERA = 104,
- R_PPC64_DTPREL16_HIGHEST = 105,
- R_PPC64_DTPREL16_HIGHESTA = 106,
- R_PPC64_TLSGD = 107,
- R_PPC64_TLSLD = 108,
- R_PPC64_REL16 = 249,
- R_PPC64_REL16_LO = 250,
- R_PPC64_REL16_HI = 251,
- R_PPC64_REL16_HA = 252
+#include "ELFRelocs/PowerPC64.def"
};
// ELF Relocation types for AArch64
-
enum {
- R_AARCH64_NONE = 0x100,
-
- R_AARCH64_ABS64 = 0x101,
- R_AARCH64_ABS32 = 0x102,
- R_AARCH64_ABS16 = 0x103,
- R_AARCH64_PREL64 = 0x104,
- R_AARCH64_PREL32 = 0x105,
- R_AARCH64_PREL16 = 0x106,
-
- R_AARCH64_MOVW_UABS_G0 = 0x107,
- R_AARCH64_MOVW_UABS_G0_NC = 0x108,
- R_AARCH64_MOVW_UABS_G1 = 0x109,
- R_AARCH64_MOVW_UABS_G1_NC = 0x10a,
- R_AARCH64_MOVW_UABS_G2 = 0x10b,
- R_AARCH64_MOVW_UABS_G2_NC = 0x10c,
- R_AARCH64_MOVW_UABS_G3 = 0x10d,
- R_AARCH64_MOVW_SABS_G0 = 0x10e,
- R_AARCH64_MOVW_SABS_G1 = 0x10f,
- R_AARCH64_MOVW_SABS_G2 = 0x110,
-
- R_AARCH64_LD_PREL_LO19 = 0x111,
- R_AARCH64_ADR_PREL_LO21 = 0x112,
- R_AARCH64_ADR_PREL_PG_HI21 = 0x113,
- R_AARCH64_ADD_ABS_LO12_NC = 0x115,
- R_AARCH64_LDST8_ABS_LO12_NC = 0x116,
-
- R_AARCH64_TSTBR14 = 0x117,
- R_AARCH64_CONDBR19 = 0x118,
- R_AARCH64_JUMP26 = 0x11a,
- R_AARCH64_CALL26 = 0x11b,
-
- R_AARCH64_LDST16_ABS_LO12_NC = 0x11c,
- R_AARCH64_LDST32_ABS_LO12_NC = 0x11d,
- R_AARCH64_LDST64_ABS_LO12_NC = 0x11e,
-
- R_AARCH64_LDST128_ABS_LO12_NC = 0x12b,
-
- R_AARCH64_GOTREL64 = 0x133,
- R_AARCH64_GOTREL32 = 0x134,
-
- R_AARCH64_ADR_GOT_PAGE = 0x137,
- R_AARCH64_LD64_GOT_LO12_NC = 0x138,
-
- R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b,
- R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c,
- R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d,
- R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e,
- R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f,
- R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210,
- R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211,
- R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212,
- R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213,
- R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214,
- R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215,
- R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216,
- R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217,
- R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218,
- R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219,
- R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a,
-
- R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b,
- R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c,
- R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d,
- R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e,
- R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f,
-
- R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220,
- R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221,
- R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222,
- R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223,
- R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224,
- R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225,
- R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226,
- R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227,
- R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228,
- R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229,
- R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a,
- R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b,
- R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c,
- R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d,
- R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e,
- R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f,
-
- R_AARCH64_TLSDESC_ADR_PAGE = 0x232,
- R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233,
- R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234,
-
- R_AARCH64_TLSDESC_CALL = 0x239,
-
- R_AARCH64_COPY = 0x400,
- R_AARCH64_GLOB_DAT = 0x401,
- R_AARCH64_JUMP_SLOT = 0x402,
- R_AARCH64_RELATIVE = 0x403,
- R_AARCH64_TLS_DTPREL64 = 0x404,
- R_AARCH64_TLS_DTPMOD64 = 0x405,
- R_AARCH64_TLS_TPREL64 = 0x406,
- R_AARCH64_TLSDESC = 0x407,
- R_AARCH64_IRELATIVE = 0x408
+#include "ELFRelocs/AArch64.def"
};
// ARM Specific e_flags
@@ -733,140 +422,8 @@ enum : unsigned {
};
// ELF Relocation types for ARM
-// Meets 2.08 ABI Specs.
-
enum {
- R_ARM_NONE = 0x00,
- R_ARM_PC24 = 0x01,
- R_ARM_ABS32 = 0x02,
- R_ARM_REL32 = 0x03,
- R_ARM_LDR_PC_G0 = 0x04,
- R_ARM_ABS16 = 0x05,
- R_ARM_ABS12 = 0x06,
- R_ARM_THM_ABS5 = 0x07,
- R_ARM_ABS8 = 0x08,
- R_ARM_SBREL32 = 0x09,
- R_ARM_THM_CALL = 0x0a,
- R_ARM_THM_PC8 = 0x0b,
- R_ARM_BREL_ADJ = 0x0c,
- R_ARM_TLS_DESC = 0x0d,
- R_ARM_THM_SWI8 = 0x0e,
- R_ARM_XPC25 = 0x0f,
- R_ARM_THM_XPC22 = 0x10,
- R_ARM_TLS_DTPMOD32 = 0x11,
- R_ARM_TLS_DTPOFF32 = 0x12,
- R_ARM_TLS_TPOFF32 = 0x13,
- R_ARM_COPY = 0x14,
- R_ARM_GLOB_DAT = 0x15,
- R_ARM_JUMP_SLOT = 0x16,
- R_ARM_RELATIVE = 0x17,
- R_ARM_GOTOFF32 = 0x18,
- R_ARM_BASE_PREL = 0x19,
- R_ARM_GOT_BREL = 0x1a,
- R_ARM_PLT32 = 0x1b,
- R_ARM_CALL = 0x1c,
- R_ARM_JUMP24 = 0x1d,
- R_ARM_THM_JUMP24 = 0x1e,
- R_ARM_BASE_ABS = 0x1f,
- R_ARM_ALU_PCREL_7_0 = 0x20,
- R_ARM_ALU_PCREL_15_8 = 0x21,
- R_ARM_ALU_PCREL_23_15 = 0x22,
- R_ARM_LDR_SBREL_11_0_NC = 0x23,
- R_ARM_ALU_SBREL_19_12_NC = 0x24,
- R_ARM_ALU_SBREL_27_20_CK = 0x25,
- R_ARM_TARGET1 = 0x26,
- R_ARM_SBREL31 = 0x27,
- R_ARM_V4BX = 0x28,
- R_ARM_TARGET2 = 0x29,
- R_ARM_PREL31 = 0x2a,
- R_ARM_MOVW_ABS_NC = 0x2b,
- R_ARM_MOVT_ABS = 0x2c,
- R_ARM_MOVW_PREL_NC = 0x2d,
- R_ARM_MOVT_PREL = 0x2e,
- R_ARM_THM_MOVW_ABS_NC = 0x2f,
- R_ARM_THM_MOVT_ABS = 0x30,
- R_ARM_THM_MOVW_PREL_NC = 0x31,
- R_ARM_THM_MOVT_PREL = 0x32,
- R_ARM_THM_JUMP19 = 0x33,
- R_ARM_THM_JUMP6 = 0x34,
- R_ARM_THM_ALU_PREL_11_0 = 0x35,
- R_ARM_THM_PC12 = 0x36,
- R_ARM_ABS32_NOI = 0x37,
- R_ARM_REL32_NOI = 0x38,
- R_ARM_ALU_PC_G0_NC = 0x39,
- R_ARM_ALU_PC_G0 = 0x3a,
- R_ARM_ALU_PC_G1_NC = 0x3b,
- R_ARM_ALU_PC_G1 = 0x3c,
- R_ARM_ALU_PC_G2 = 0x3d,
- R_ARM_LDR_PC_G1 = 0x3e,
- R_ARM_LDR_PC_G2 = 0x3f,
- R_ARM_LDRS_PC_G0 = 0x40,
- R_ARM_LDRS_PC_G1 = 0x41,
- R_ARM_LDRS_PC_G2 = 0x42,
- R_ARM_LDC_PC_G0 = 0x43,
- R_ARM_LDC_PC_G1 = 0x44,
- R_ARM_LDC_PC_G2 = 0x45,
- R_ARM_ALU_SB_G0_NC = 0x46,
- R_ARM_ALU_SB_G0 = 0x47,
- R_ARM_ALU_SB_G1_NC = 0x48,
- R_ARM_ALU_SB_G1 = 0x49,
- R_ARM_ALU_SB_G2 = 0x4a,
- R_ARM_LDR_SB_G0 = 0x4b,
- R_ARM_LDR_SB_G1 = 0x4c,
- R_ARM_LDR_SB_G2 = 0x4d,
- R_ARM_LDRS_SB_G0 = 0x4e,
- R_ARM_LDRS_SB_G1 = 0x4f,
- R_ARM_LDRS_SB_G2 = 0x50,
- R_ARM_LDC_SB_G0 = 0x51,
- R_ARM_LDC_SB_G1 = 0x52,
- R_ARM_LDC_SB_G2 = 0x53,
- R_ARM_MOVW_BREL_NC = 0x54,
- R_ARM_MOVT_BREL = 0x55,
- R_ARM_MOVW_BREL = 0x56,
- R_ARM_THM_MOVW_BREL_NC = 0x57,
- R_ARM_THM_MOVT_BREL = 0x58,
- R_ARM_THM_MOVW_BREL = 0x59,
- R_ARM_TLS_GOTDESC = 0x5a,
- R_ARM_TLS_CALL = 0x5b,
- R_ARM_TLS_DESCSEQ = 0x5c,
- R_ARM_THM_TLS_CALL = 0x5d,
- R_ARM_PLT32_ABS = 0x5e,
- R_ARM_GOT_ABS = 0x5f,
- R_ARM_GOT_PREL = 0x60,
- R_ARM_GOT_BREL12 = 0x61,
- R_ARM_GOTOFF12 = 0x62,
- R_ARM_GOTRELAX = 0x63,
- R_ARM_GNU_VTENTRY = 0x64,
- R_ARM_GNU_VTINHERIT = 0x65,
- R_ARM_THM_JUMP11 = 0x66,
- R_ARM_THM_JUMP8 = 0x67,
- R_ARM_TLS_GD32 = 0x68,
- R_ARM_TLS_LDM32 = 0x69,
- R_ARM_TLS_LDO32 = 0x6a,
- R_ARM_TLS_IE32 = 0x6b,
- R_ARM_TLS_LE32 = 0x6c,
- R_ARM_TLS_LDO12 = 0x6d,
- R_ARM_TLS_LE12 = 0x6e,
- R_ARM_TLS_IE12GP = 0x6f,
- R_ARM_PRIVATE_0 = 0x70,
- R_ARM_PRIVATE_1 = 0x71,
- R_ARM_PRIVATE_2 = 0x72,
- R_ARM_PRIVATE_3 = 0x73,
- R_ARM_PRIVATE_4 = 0x74,
- R_ARM_PRIVATE_5 = 0x75,
- R_ARM_PRIVATE_6 = 0x76,
- R_ARM_PRIVATE_7 = 0x77,
- R_ARM_PRIVATE_8 = 0x78,
- R_ARM_PRIVATE_9 = 0x79,
- R_ARM_PRIVATE_10 = 0x7a,
- R_ARM_PRIVATE_11 = 0x7b,
- R_ARM_PRIVATE_12 = 0x7c,
- R_ARM_PRIVATE_13 = 0x7d,
- R_ARM_PRIVATE_14 = 0x7e,
- R_ARM_PRIVATE_15 = 0x7f,
- R_ARM_ME_TOO = 0x80,
- R_ARM_THM_TLS_DESCSEQ16 = 0x81,
- R_ARM_THM_TLS_DESCSEQ32 = 0x82
+#include "ELFRelocs/ARM.def"
};
// Mips Specific e_flags
@@ -897,8 +454,8 @@ enum : unsigned {
EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set
EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h
EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h
- EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2
- EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2
+ EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5
+ EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5
EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6
EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6
EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant
@@ -906,85 +463,7 @@ enum : unsigned {
// ELF Relocation types for Mips
enum {
- R_MIPS_NONE = 0,
- R_MIPS_16 = 1,
- R_MIPS_32 = 2,
- R_MIPS_REL32 = 3,
- R_MIPS_26 = 4,
- R_MIPS_HI16 = 5,
- R_MIPS_LO16 = 6,
- R_MIPS_GPREL16 = 7,
- R_MIPS_LITERAL = 8,
- R_MIPS_GOT16 = 9,
- R_MIPS_PC16 = 10,
- R_MIPS_CALL16 = 11,
- R_MIPS_GPREL32 = 12,
- R_MIPS_UNUSED1 = 13,
- R_MIPS_UNUSED2 = 14,
- R_MIPS_SHIFT5 = 16,
- R_MIPS_SHIFT6 = 17,
- R_MIPS_64 = 18,
- R_MIPS_GOT_DISP = 19,
- R_MIPS_GOT_PAGE = 20,
- R_MIPS_GOT_OFST = 21,
- R_MIPS_GOT_HI16 = 22,
- R_MIPS_GOT_LO16 = 23,
- R_MIPS_SUB = 24,
- R_MIPS_INSERT_A = 25,
- R_MIPS_INSERT_B = 26,
- R_MIPS_DELETE = 27,
- R_MIPS_HIGHER = 28,
- R_MIPS_HIGHEST = 29,
- R_MIPS_CALL_HI16 = 30,
- R_MIPS_CALL_LO16 = 31,
- R_MIPS_SCN_DISP = 32,
- R_MIPS_REL16 = 33,
- R_MIPS_ADD_IMMEDIATE = 34,
- R_MIPS_PJUMP = 35,
- R_MIPS_RELGOT = 36,
- R_MIPS_JALR = 37,
- R_MIPS_TLS_DTPMOD32 = 38,
- R_MIPS_TLS_DTPREL32 = 39,
- R_MIPS_TLS_DTPMOD64 = 40,
- R_MIPS_TLS_DTPREL64 = 41,
- R_MIPS_TLS_GD = 42,
- R_MIPS_TLS_LDM = 43,
- R_MIPS_TLS_DTPREL_HI16 = 44,
- R_MIPS_TLS_DTPREL_LO16 = 45,
- R_MIPS_TLS_GOTTPREL = 46,
- R_MIPS_TLS_TPREL32 = 47,
- R_MIPS_TLS_TPREL64 = 48,
- R_MIPS_TLS_TPREL_HI16 = 49,
- R_MIPS_TLS_TPREL_LO16 = 50,
- R_MIPS_GLOB_DAT = 51,
- R_MIPS_PC21_S2 = 60,
- R_MIPS_PC26_S2 = 61,
- R_MIPS_PC18_S3 = 62,
- R_MIPS_PC19_S2 = 63,
- R_MIPS_PCHI16 = 64,
- R_MIPS_PCLO16 = 65,
- R_MIPS16_GOT16 = 102,
- R_MIPS16_HI16 = 104,
- R_MIPS16_LO16 = 105,
- R_MIPS_COPY = 126,
- R_MIPS_JUMP_SLOT = 127,
- R_MICROMIPS_26_S1 = 133,
- R_MICROMIPS_HI16 = 134,
- R_MICROMIPS_LO16 = 135,
- R_MICROMIPS_GOT16 = 138,
- R_MICROMIPS_PC16_S1 = 141,
- R_MICROMIPS_CALL16 = 142,
- R_MICROMIPS_GOT_DISP = 145,
- R_MICROMIPS_GOT_PAGE = 146,
- R_MICROMIPS_GOT_OFST = 147,
- R_MICROMIPS_TLS_GD = 162,
- R_MICROMIPS_TLS_LDM = 163,
- R_MICROMIPS_TLS_DTPREL_HI16 = 164,
- R_MICROMIPS_TLS_DTPREL_LO16 = 165,
- R_MICROMIPS_TLS_TPREL_HI16 = 169,
- R_MICROMIPS_TLS_TPREL_LO16 = 170,
- R_MIPS_NUM = 218,
- R_MIPS_PC32 = 248
+#include "ELFRelocs/Mips.def"
};
// Special values for the st_other field in the symbol table entry for MIPS.
@@ -996,6 +475,22 @@ enum {
STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16
};
+// .MIPS.options section descriptor kinds
+enum {
+ ODK_NULL = 0, // Undefined
+ ODK_REGINFO = 1, // Register usage information
+ ODK_EXCEPTIONS = 2, // Exception processing options
+ ODK_PAD = 3, // Section padding options
+ ODK_HWPATCH = 4, // Hardware patches applied
+ ODK_FILL = 5, // Linker fill value
+ ODK_TAGS = 6, // Space for tool identification
+ ODK_HWAND = 7, // Hardware AND patches applied
+ ODK_HWOR = 8, // Hardware OR patches applied
+ ODK_GP_GROUP = 9, // GP group to use for text/data sections
+ ODK_IDENT = 10, // ID information
+ ODK_PAGESIZE = 11 // Page size information
+};
+
// Hexagon Specific e_flags
// Release 5 ABI
enum {
@@ -1025,250 +520,22 @@ enum {
};
// ELF Relocation types for Hexagon
-// Release 5 ABI
enum {
- R_HEX_NONE = 0,
- R_HEX_B22_PCREL = 1,
- R_HEX_B15_PCREL = 2,
- R_HEX_B7_PCREL = 3,
- R_HEX_LO16 = 4,
- R_HEX_HI16 = 5,
- R_HEX_32 = 6,
- R_HEX_16 = 7,
- R_HEX_8 = 8,
- R_HEX_GPREL16_0 = 9,
- R_HEX_GPREL16_1 = 10,
- R_HEX_GPREL16_2 = 11,
- R_HEX_GPREL16_3 = 12,
- R_HEX_HL16 = 13,
- R_HEX_B13_PCREL = 14,
- R_HEX_B9_PCREL = 15,
- R_HEX_B32_PCREL_X = 16,
- R_HEX_32_6_X = 17,
- R_HEX_B22_PCREL_X = 18,
- R_HEX_B15_PCREL_X = 19,
- R_HEX_B13_PCREL_X = 20,
- R_HEX_B9_PCREL_X = 21,
- R_HEX_B7_PCREL_X = 22,
- R_HEX_16_X = 23,
- R_HEX_12_X = 24,
- R_HEX_11_X = 25,
- R_HEX_10_X = 26,
- R_HEX_9_X = 27,
- R_HEX_8_X = 28,
- R_HEX_7_X = 29,
- R_HEX_6_X = 30,
- R_HEX_32_PCREL = 31,
- R_HEX_COPY = 32,
- R_HEX_GLOB_DAT = 33,
- R_HEX_JMP_SLOT = 34,
- R_HEX_RELATIVE = 35,
- R_HEX_PLT_B22_PCREL = 36,
- R_HEX_GOTREL_LO16 = 37,
- R_HEX_GOTREL_HI16 = 38,
- R_HEX_GOTREL_32 = 39,
- R_HEX_GOT_LO16 = 40,
- R_HEX_GOT_HI16 = 41,
- R_HEX_GOT_32 = 42,
- R_HEX_GOT_16 = 43,
- R_HEX_DTPMOD_32 = 44,
- R_HEX_DTPREL_LO16 = 45,
- R_HEX_DTPREL_HI16 = 46,
- R_HEX_DTPREL_32 = 47,
- R_HEX_DTPREL_16 = 48,
- R_HEX_GD_PLT_B22_PCREL = 49,
- R_HEX_GD_GOT_LO16 = 50,
- R_HEX_GD_GOT_HI16 = 51,
- R_HEX_GD_GOT_32 = 52,
- R_HEX_GD_GOT_16 = 53,
- R_HEX_IE_LO16 = 54,
- R_HEX_IE_HI16 = 55,
- R_HEX_IE_32 = 56,
- R_HEX_IE_GOT_LO16 = 57,
- R_HEX_IE_GOT_HI16 = 58,
- R_HEX_IE_GOT_32 = 59,
- R_HEX_IE_GOT_16 = 60,
- R_HEX_TPREL_LO16 = 61,
- R_HEX_TPREL_HI16 = 62,
- R_HEX_TPREL_32 = 63,
- R_HEX_TPREL_16 = 64,
- R_HEX_6_PCREL_X = 65,
- R_HEX_GOTREL_32_6_X = 66,
- R_HEX_GOTREL_16_X = 67,
- R_HEX_GOTREL_11_X = 68,
- R_HEX_GOT_32_6_X = 69,
- R_HEX_GOT_16_X = 70,
- R_HEX_GOT_11_X = 71,
- R_HEX_DTPREL_32_6_X = 72,
- R_HEX_DTPREL_16_X = 73,
- R_HEX_DTPREL_11_X = 74,
- R_HEX_GD_GOT_32_6_X = 75,
- R_HEX_GD_GOT_16_X = 76,
- R_HEX_GD_GOT_11_X = 77,
- R_HEX_IE_32_6_X = 78,
- R_HEX_IE_16_X = 79,
- R_HEX_IE_GOT_32_6_X = 80,
- R_HEX_IE_GOT_16_X = 81,
- R_HEX_IE_GOT_11_X = 82,
- R_HEX_TPREL_32_6_X = 83,
- R_HEX_TPREL_16_X = 84,
- R_HEX_TPREL_11_X = 85
+#include "ELFRelocs/Hexagon.def"
};
// ELF Relocation types for S390/zSeries
enum {
- R_390_NONE = 0,
- R_390_8 = 1,
- R_390_12 = 2,
- R_390_16 = 3,
- R_390_32 = 4,
- R_390_PC32 = 5,
- R_390_GOT12 = 6,
- R_390_GOT32 = 7,
- R_390_PLT32 = 8,
- R_390_COPY = 9,
- R_390_GLOB_DAT = 10,
- R_390_JMP_SLOT = 11,
- R_390_RELATIVE = 12,
- R_390_GOTOFF = 13,
- R_390_GOTPC = 14,
- R_390_GOT16 = 15,
- R_390_PC16 = 16,
- R_390_PC16DBL = 17,
- R_390_PLT16DBL = 18,
- R_390_PC32DBL = 19,
- R_390_PLT32DBL = 20,
- R_390_GOTPCDBL = 21,
- R_390_64 = 22,
- R_390_PC64 = 23,
- R_390_GOT64 = 24,
- R_390_PLT64 = 25,
- R_390_GOTENT = 26,
- R_390_GOTOFF16 = 27,
- R_390_GOTOFF64 = 28,
- R_390_GOTPLT12 = 29,
- R_390_GOTPLT16 = 30,
- R_390_GOTPLT32 = 31,
- R_390_GOTPLT64 = 32,
- R_390_GOTPLTENT = 33,
- R_390_PLTOFF16 = 34,
- R_390_PLTOFF32 = 35,
- R_390_PLTOFF64 = 36,
- R_390_TLS_LOAD = 37,
- R_390_TLS_GDCALL = 38,
- R_390_TLS_LDCALL = 39,
- R_390_TLS_GD32 = 40,
- R_390_TLS_GD64 = 41,
- R_390_TLS_GOTIE12 = 42,
- R_390_TLS_GOTIE32 = 43,
- R_390_TLS_GOTIE64 = 44,
- R_390_TLS_LDM32 = 45,
- R_390_TLS_LDM64 = 46,
- R_390_TLS_IE32 = 47,
- R_390_TLS_IE64 = 48,
- R_390_TLS_IEENT = 49,
- R_390_TLS_LE32 = 50,
- R_390_TLS_LE64 = 51,
- R_390_TLS_LDO32 = 52,
- R_390_TLS_LDO64 = 53,
- R_390_TLS_DTPMOD = 54,
- R_390_TLS_DTPOFF = 55,
- R_390_TLS_TPOFF = 56,
- R_390_20 = 57,
- R_390_GOT20 = 58,
- R_390_GOTPLT20 = 59,
- R_390_TLS_GOTIE20 = 60,
- R_390_IRELATIVE = 61
+#include "ELFRelocs/SystemZ.def"
};
// ELF Relocation type for Sparc.
enum {
- R_SPARC_NONE = 0,
- R_SPARC_8 = 1,
- R_SPARC_16 = 2,
- R_SPARC_32 = 3,
- R_SPARC_DISP8 = 4,
- R_SPARC_DISP16 = 5,
- R_SPARC_DISP32 = 6,
- R_SPARC_WDISP30 = 7,
- R_SPARC_WDISP22 = 8,
- R_SPARC_HI22 = 9,
- R_SPARC_22 = 10,
- R_SPARC_13 = 11,
- R_SPARC_LO10 = 12,
- R_SPARC_GOT10 = 13,
- R_SPARC_GOT13 = 14,
- R_SPARC_GOT22 = 15,
- R_SPARC_PC10 = 16,
- R_SPARC_PC22 = 17,
- R_SPARC_WPLT30 = 18,
- R_SPARC_COPY = 19,
- R_SPARC_GLOB_DAT = 20,
- R_SPARC_JMP_SLOT = 21,
- R_SPARC_RELATIVE = 22,
- R_SPARC_UA32 = 23,
- R_SPARC_PLT32 = 24,
- R_SPARC_HIPLT22 = 25,
- R_SPARC_LOPLT10 = 26,
- R_SPARC_PCPLT32 = 27,
- R_SPARC_PCPLT22 = 28,
- R_SPARC_PCPLT10 = 29,
- R_SPARC_10 = 30,
- R_SPARC_11 = 31,
- R_SPARC_64 = 32,
- R_SPARC_OLO10 = 33,
- R_SPARC_HH22 = 34,
- R_SPARC_HM10 = 35,
- R_SPARC_LM22 = 36,
- R_SPARC_PC_HH22 = 37,
- R_SPARC_PC_HM10 = 38,
- R_SPARC_PC_LM22 = 39,
- R_SPARC_WDISP16 = 40,
- R_SPARC_WDISP19 = 41,
- R_SPARC_7 = 43,
- R_SPARC_5 = 44,
- R_SPARC_6 = 45,
- R_SPARC_DISP64 = 46,
- R_SPARC_PLT64 = 47,
- R_SPARC_HIX22 = 48,
- R_SPARC_LOX10 = 49,
- R_SPARC_H44 = 50,
- R_SPARC_M44 = 51,
- R_SPARC_L44 = 52,
- R_SPARC_REGISTER = 53,
- R_SPARC_UA64 = 54,
- R_SPARC_UA16 = 55,
- R_SPARC_TLS_GD_HI22 = 56,
- R_SPARC_TLS_GD_LO10 = 57,
- R_SPARC_TLS_GD_ADD = 58,
- R_SPARC_TLS_GD_CALL = 59,
- R_SPARC_TLS_LDM_HI22 = 60,
- R_SPARC_TLS_LDM_LO10 = 61,
- R_SPARC_TLS_LDM_ADD = 62,
- R_SPARC_TLS_LDM_CALL = 63,
- R_SPARC_TLS_LDO_HIX22 = 64,
- R_SPARC_TLS_LDO_LOX10 = 65,
- R_SPARC_TLS_LDO_ADD = 66,
- R_SPARC_TLS_IE_HI22 = 67,
- R_SPARC_TLS_IE_LO10 = 68,
- R_SPARC_TLS_IE_LD = 69,
- R_SPARC_TLS_IE_LDX = 70,
- R_SPARC_TLS_IE_ADD = 71,
- R_SPARC_TLS_LE_HIX22 = 72,
- R_SPARC_TLS_LE_LOX10 = 73,
- R_SPARC_TLS_DTPMOD32 = 74,
- R_SPARC_TLS_DTPMOD64 = 75,
- R_SPARC_TLS_DTPOFF32 = 76,
- R_SPARC_TLS_DTPOFF64 = 77,
- R_SPARC_TLS_TPOFF32 = 78,
- R_SPARC_TLS_TPOFF64 = 79,
- R_SPARC_GOTDATA_HIX22 = 80,
- R_SPARC_GOTDATA_LOX22 = 81,
- R_SPARC_GOTDATA_OP_HIX22 = 82,
- R_SPARC_GOTDATA_OP_LOX22 = 83,
- R_SPARC_GOTDATA_OP = 84
+#include "ELFRelocs/Sparc.def"
};
+#undef ELF_RELOC
+
// Section header.
struct Elf32_Shdr {
Elf32_Word sh_name; // Section name (index into string table)
@@ -1510,6 +777,7 @@ enum {
STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def
STB_GLOBAL = 1, // Global symbol, visible to all object files being combined
STB_WEAK = 2, // Weak symbol, like global but lower-precedence
+ STB_GNU_UNIQUE = 10,
STB_LOOS = 10, // Lowest operating system-specific binding type
STB_HIOS = 12, // Highest operating system-specific binding type
STB_LOPROC = 13, // Lowest processor-specific binding type
@@ -1544,6 +812,14 @@ enum {
STN_UNDEF = 0
};
+// Special relocation symbols used in the MIPS64 ELF relocation entries
+enum {
+ RSS_UNDEF = 0, // None
+ RSS_GP = 1, // Value of gp
+ RSS_GP0 = 2, // Value of gp used to create object being relocated
+ RSS_LOC = 3 // Address of location being relocated
+};
+
// Relocation entry, without explicit addend.
struct Elf32_Rel {
Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr)
diff --git a/include/llvm/Support/ELFRelocs/AArch64.def b/include/llvm/Support/ELFRelocs/AArch64.def
new file mode 100644
index 0000000..aa0c560
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/AArch64.def
@@ -0,0 +1,147 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// ABI release 1.0
+ELF_RELOC(R_AARCH64_NONE, 0)
+
+ELF_RELOC(R_AARCH64_ABS64, 0x101)
+ELF_RELOC(R_AARCH64_ABS32, 0x102)
+ELF_RELOC(R_AARCH64_ABS16, 0x103)
+ELF_RELOC(R_AARCH64_PREL64, 0x104)
+ELF_RELOC(R_AARCH64_PREL32, 0x105)
+ELF_RELOC(R_AARCH64_PREL16, 0x106)
+
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0, 0x107)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 0x108)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1, 0x109)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 0x10a)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2, 0x10b)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 0x10c)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G3, 0x10d)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G0, 0x10e)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G1, 0x10f)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G2, 0x110)
+
+ELF_RELOC(R_AARCH64_LD_PREL_LO19, 0x111)
+ELF_RELOC(R_AARCH64_ADR_PREL_LO21, 0x112)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 0x113)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 0x114)
+ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 0x115)
+ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 0x116)
+
+ELF_RELOC(R_AARCH64_TSTBR14, 0x117)
+ELF_RELOC(R_AARCH64_CONDBR19, 0x118)
+ELF_RELOC(R_AARCH64_JUMP26, 0x11a)
+ELF_RELOC(R_AARCH64_CALL26, 0x11b)
+
+ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 0x11c)
+ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 0x11d)
+ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 0x11e)
+
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0, 0x11f)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 0x120)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1, 0x121)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 0x122)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2, 0x123)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 0x124)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G3, 0x125)
+
+ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 0x12b)
+
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 0x12c)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 0x12d)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 0x12e)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 0x12f)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 0x130)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 0x131)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 0x132)
+
+ELF_RELOC(R_AARCH64_GOTREL64, 0x133)
+ELF_RELOC(R_AARCH64_GOTREL32, 0x134)
+
+ELF_RELOC(R_AARCH64_GOT_LD_PREL19, 0x135)
+ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 0x136)
+ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137)
+ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138)
+ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139)
+
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200)
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201)
+ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1, 0x203)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 0x204)
+
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 0x205)
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 0x206)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 0x207)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1, 0x208)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 0x209)
+ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19, 0x20a)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 0x20b)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 0x20c)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 0x20d)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 0x20e)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 0x20f)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 0x210)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12, 0x211)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 0x212)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 0x213)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 0x214)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 0x215)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 0x216)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 0x217)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 0x218)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 0x219)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 0x21a)
+
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 0x21b)
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 0x21c)
+ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x21d)
+ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0x21e)
+ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 0x21f)
+
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 0x220)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 0x221)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 0x222)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 0x223)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 0x224)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x225)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 0x226)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x227)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 0x228)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 0x229)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 0x22a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 0x22b)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 0x22c)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 0x22d)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 0x22e)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 0x22f)
+
+ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 0x230)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 0x231)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 0x232)
+ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC, 0x233)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC, 0x234)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1, 0x235)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 0x236)
+ELF_RELOC(R_AARCH64_TLSDESC_LDR, 0x237)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD, 0x238)
+ELF_RELOC(R_AARCH64_TLSDESC_CALL, 0x239)
+
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b)
+
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c)
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d)
+
+ELF_RELOC(R_AARCH64_COPY, 0x400)
+ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401)
+ELF_RELOC(R_AARCH64_JUMP_SLOT, 0x402)
+ELF_RELOC(R_AARCH64_RELATIVE, 0x403)
+ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x404)
+ELF_RELOC(R_AARCH64_TLS_DTPMOD64, 0x405)
+ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406)
+ELF_RELOC(R_AARCH64_TLSDESC, 0x407)
+ELF_RELOC(R_AARCH64_IRELATIVE, 0x408)
diff --git a/include/llvm/Support/ELFRelocs/ARM.def b/include/llvm/Support/ELFRelocs/ARM.def
new file mode 100644
index 0000000..730fc5b
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/ARM.def
@@ -0,0 +1,138 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Meets 2.09 ABI Specs.
+ELF_RELOC(R_ARM_NONE, 0x00)
+ELF_RELOC(R_ARM_PC24, 0x01)
+ELF_RELOC(R_ARM_ABS32, 0x02)
+ELF_RELOC(R_ARM_REL32, 0x03)
+ELF_RELOC(R_ARM_LDR_PC_G0, 0x04)
+ELF_RELOC(R_ARM_ABS16, 0x05)
+ELF_RELOC(R_ARM_ABS12, 0x06)
+ELF_RELOC(R_ARM_THM_ABS5, 0x07)
+ELF_RELOC(R_ARM_ABS8, 0x08)
+ELF_RELOC(R_ARM_SBREL32, 0x09)
+ELF_RELOC(R_ARM_THM_CALL, 0x0a)
+ELF_RELOC(R_ARM_THM_PC8, 0x0b)
+ELF_RELOC(R_ARM_BREL_ADJ, 0x0c)
+ELF_RELOC(R_ARM_TLS_DESC, 0x0d)
+ELF_RELOC(R_ARM_THM_SWI8, 0x0e)
+ELF_RELOC(R_ARM_XPC25, 0x0f)
+ELF_RELOC(R_ARM_THM_XPC22, 0x10)
+ELF_RELOC(R_ARM_TLS_DTPMOD32, 0x11)
+ELF_RELOC(R_ARM_TLS_DTPOFF32, 0x12)
+ELF_RELOC(R_ARM_TLS_TPOFF32, 0x13)
+ELF_RELOC(R_ARM_COPY, 0x14)
+ELF_RELOC(R_ARM_GLOB_DAT, 0x15)
+ELF_RELOC(R_ARM_JUMP_SLOT, 0x16)
+ELF_RELOC(R_ARM_RELATIVE, 0x17)
+ELF_RELOC(R_ARM_GOTOFF32, 0x18)
+ELF_RELOC(R_ARM_BASE_PREL, 0x19)
+ELF_RELOC(R_ARM_GOT_BREL, 0x1a)
+ELF_RELOC(R_ARM_PLT32, 0x1b)
+ELF_RELOC(R_ARM_CALL, 0x1c)
+ELF_RELOC(R_ARM_JUMP24, 0x1d)
+ELF_RELOC(R_ARM_THM_JUMP24, 0x1e)
+ELF_RELOC(R_ARM_BASE_ABS, 0x1f)
+ELF_RELOC(R_ARM_ALU_PCREL_7_0, 0x20)
+ELF_RELOC(R_ARM_ALU_PCREL_15_8, 0x21)
+ELF_RELOC(R_ARM_ALU_PCREL_23_15, 0x22)
+ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC, 0x23)
+ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC, 0x24)
+ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK, 0x25)
+ELF_RELOC(R_ARM_TARGET1, 0x26)
+ELF_RELOC(R_ARM_SBREL31, 0x27)
+ELF_RELOC(R_ARM_V4BX, 0x28)
+ELF_RELOC(R_ARM_TARGET2, 0x29)
+ELF_RELOC(R_ARM_PREL31, 0x2a)
+ELF_RELOC(R_ARM_MOVW_ABS_NC, 0x2b)
+ELF_RELOC(R_ARM_MOVT_ABS, 0x2c)
+ELF_RELOC(R_ARM_MOVW_PREL_NC, 0x2d)
+ELF_RELOC(R_ARM_MOVT_PREL, 0x2e)
+ELF_RELOC(R_ARM_THM_MOVW_ABS_NC, 0x2f)
+ELF_RELOC(R_ARM_THM_MOVT_ABS, 0x30)
+ELF_RELOC(R_ARM_THM_MOVW_PREL_NC, 0x31)
+ELF_RELOC(R_ARM_THM_MOVT_PREL, 0x32)
+ELF_RELOC(R_ARM_THM_JUMP19, 0x33)
+ELF_RELOC(R_ARM_THM_JUMP6, 0x34)
+ELF_RELOC(R_ARM_THM_ALU_PREL_11_0, 0x35)
+ELF_RELOC(R_ARM_THM_PC12, 0x36)
+ELF_RELOC(R_ARM_ABS32_NOI, 0x37)
+ELF_RELOC(R_ARM_REL32_NOI, 0x38)
+ELF_RELOC(R_ARM_ALU_PC_G0_NC, 0x39)
+ELF_RELOC(R_ARM_ALU_PC_G0, 0x3a)
+ELF_RELOC(R_ARM_ALU_PC_G1_NC, 0x3b)
+ELF_RELOC(R_ARM_ALU_PC_G1, 0x3c)
+ELF_RELOC(R_ARM_ALU_PC_G2, 0x3d)
+ELF_RELOC(R_ARM_LDR_PC_G1, 0x3e)
+ELF_RELOC(R_ARM_LDR_PC_G2, 0x3f)
+ELF_RELOC(R_ARM_LDRS_PC_G0, 0x40)
+ELF_RELOC(R_ARM_LDRS_PC_G1, 0x41)
+ELF_RELOC(R_ARM_LDRS_PC_G2, 0x42)
+ELF_RELOC(R_ARM_LDC_PC_G0, 0x43)
+ELF_RELOC(R_ARM_LDC_PC_G1, 0x44)
+ELF_RELOC(R_ARM_LDC_PC_G2, 0x45)
+ELF_RELOC(R_ARM_ALU_SB_G0_NC, 0x46)
+ELF_RELOC(R_ARM_ALU_SB_G0, 0x47)
+ELF_RELOC(R_ARM_ALU_SB_G1_NC, 0x48)
+ELF_RELOC(R_ARM_ALU_SB_G1, 0x49)
+ELF_RELOC(R_ARM_ALU_SB_G2, 0x4a)
+ELF_RELOC(R_ARM_LDR_SB_G0, 0x4b)
+ELF_RELOC(R_ARM_LDR_SB_G1, 0x4c)
+ELF_RELOC(R_ARM_LDR_SB_G2, 0x4d)
+ELF_RELOC(R_ARM_LDRS_SB_G0, 0x4e)
+ELF_RELOC(R_ARM_LDRS_SB_G1, 0x4f)
+ELF_RELOC(R_ARM_LDRS_SB_G2, 0x50)
+ELF_RELOC(R_ARM_LDC_SB_G0, 0x51)
+ELF_RELOC(R_ARM_LDC_SB_G1, 0x52)
+ELF_RELOC(R_ARM_LDC_SB_G2, 0x53)
+ELF_RELOC(R_ARM_MOVW_BREL_NC, 0x54)
+ELF_RELOC(R_ARM_MOVT_BREL, 0x55)
+ELF_RELOC(R_ARM_MOVW_BREL, 0x56)
+ELF_RELOC(R_ARM_THM_MOVW_BREL_NC, 0x57)
+ELF_RELOC(R_ARM_THM_MOVT_BREL, 0x58)
+ELF_RELOC(R_ARM_THM_MOVW_BREL, 0x59)
+ELF_RELOC(R_ARM_TLS_GOTDESC, 0x5a)
+ELF_RELOC(R_ARM_TLS_CALL, 0x5b)
+ELF_RELOC(R_ARM_TLS_DESCSEQ, 0x5c)
+ELF_RELOC(R_ARM_THM_TLS_CALL, 0x5d)
+ELF_RELOC(R_ARM_PLT32_ABS, 0x5e)
+ELF_RELOC(R_ARM_GOT_ABS, 0x5f)
+ELF_RELOC(R_ARM_GOT_PREL, 0x60)
+ELF_RELOC(R_ARM_GOT_BREL12, 0x61)
+ELF_RELOC(R_ARM_GOTOFF12, 0x62)
+ELF_RELOC(R_ARM_GOTRELAX, 0x63)
+ELF_RELOC(R_ARM_GNU_VTENTRY, 0x64)
+ELF_RELOC(R_ARM_GNU_VTINHERIT, 0x65)
+ELF_RELOC(R_ARM_THM_JUMP11, 0x66)
+ELF_RELOC(R_ARM_THM_JUMP8, 0x67)
+ELF_RELOC(R_ARM_TLS_GD32, 0x68)
+ELF_RELOC(R_ARM_TLS_LDM32, 0x69)
+ELF_RELOC(R_ARM_TLS_LDO32, 0x6a)
+ELF_RELOC(R_ARM_TLS_IE32, 0x6b)
+ELF_RELOC(R_ARM_TLS_LE32, 0x6c)
+ELF_RELOC(R_ARM_TLS_LDO12, 0x6d)
+ELF_RELOC(R_ARM_TLS_LE12, 0x6e)
+ELF_RELOC(R_ARM_TLS_IE12GP, 0x6f)
+ELF_RELOC(R_ARM_PRIVATE_0, 0x70)
+ELF_RELOC(R_ARM_PRIVATE_1, 0x71)
+ELF_RELOC(R_ARM_PRIVATE_2, 0x72)
+ELF_RELOC(R_ARM_PRIVATE_3, 0x73)
+ELF_RELOC(R_ARM_PRIVATE_4, 0x74)
+ELF_RELOC(R_ARM_PRIVATE_5, 0x75)
+ELF_RELOC(R_ARM_PRIVATE_6, 0x76)
+ELF_RELOC(R_ARM_PRIVATE_7, 0x77)
+ELF_RELOC(R_ARM_PRIVATE_8, 0x78)
+ELF_RELOC(R_ARM_PRIVATE_9, 0x79)
+ELF_RELOC(R_ARM_PRIVATE_10, 0x7a)
+ELF_RELOC(R_ARM_PRIVATE_11, 0x7b)
+ELF_RELOC(R_ARM_PRIVATE_12, 0x7c)
+ELF_RELOC(R_ARM_PRIVATE_13, 0x7d)
+ELF_RELOC(R_ARM_PRIVATE_14, 0x7e)
+ELF_RELOC(R_ARM_PRIVATE_15, 0x7f)
+ELF_RELOC(R_ARM_ME_TOO, 0x80)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82)
+ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def
new file mode 100644
index 0000000..c9d35b8
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -0,0 +1,92 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Release 5 ABI
+ELF_RELOC(R_HEX_NONE, 0)
+ELF_RELOC(R_HEX_B22_PCREL, 1)
+ELF_RELOC(R_HEX_B15_PCREL, 2)
+ELF_RELOC(R_HEX_B7_PCREL, 3)
+ELF_RELOC(R_HEX_LO16, 4)
+ELF_RELOC(R_HEX_HI16, 5)
+ELF_RELOC(R_HEX_32, 6)
+ELF_RELOC(R_HEX_16, 7)
+ELF_RELOC(R_HEX_8, 8)
+ELF_RELOC(R_HEX_GPREL16_0, 9)
+ELF_RELOC(R_HEX_GPREL16_1, 10)
+ELF_RELOC(R_HEX_GPREL16_2, 11)
+ELF_RELOC(R_HEX_GPREL16_3, 12)
+ELF_RELOC(R_HEX_HL16, 13)
+ELF_RELOC(R_HEX_B13_PCREL, 14)
+ELF_RELOC(R_HEX_B9_PCREL, 15)
+ELF_RELOC(R_HEX_B32_PCREL_X, 16)
+ELF_RELOC(R_HEX_32_6_X, 17)
+ELF_RELOC(R_HEX_B22_PCREL_X, 18)
+ELF_RELOC(R_HEX_B15_PCREL_X, 19)
+ELF_RELOC(R_HEX_B13_PCREL_X, 20)
+ELF_RELOC(R_HEX_B9_PCREL_X, 21)
+ELF_RELOC(R_HEX_B7_PCREL_X, 22)
+ELF_RELOC(R_HEX_16_X, 23)
+ELF_RELOC(R_HEX_12_X, 24)
+ELF_RELOC(R_HEX_11_X, 25)
+ELF_RELOC(R_HEX_10_X, 26)
+ELF_RELOC(R_HEX_9_X, 27)
+ELF_RELOC(R_HEX_8_X, 28)
+ELF_RELOC(R_HEX_7_X, 29)
+ELF_RELOC(R_HEX_6_X, 30)
+ELF_RELOC(R_HEX_32_PCREL, 31)
+ELF_RELOC(R_HEX_COPY, 32)
+ELF_RELOC(R_HEX_GLOB_DAT, 33)
+ELF_RELOC(R_HEX_JMP_SLOT, 34)
+ELF_RELOC(R_HEX_RELATIVE, 35)
+ELF_RELOC(R_HEX_PLT_B22_PCREL, 36)
+ELF_RELOC(R_HEX_GOTREL_LO16, 37)
+ELF_RELOC(R_HEX_GOTREL_HI16, 38)
+ELF_RELOC(R_HEX_GOTREL_32, 39)
+ELF_RELOC(R_HEX_GOT_LO16, 40)
+ELF_RELOC(R_HEX_GOT_HI16, 41)
+ELF_RELOC(R_HEX_GOT_32, 42)
+ELF_RELOC(R_HEX_GOT_16, 43)
+ELF_RELOC(R_HEX_DTPMOD_32, 44)
+ELF_RELOC(R_HEX_DTPREL_LO16, 45)
+ELF_RELOC(R_HEX_DTPREL_HI16, 46)
+ELF_RELOC(R_HEX_DTPREL_32, 47)
+ELF_RELOC(R_HEX_DTPREL_16, 48)
+ELF_RELOC(R_HEX_GD_PLT_B22_PCREL, 49)
+ELF_RELOC(R_HEX_GD_GOT_LO16, 50)
+ELF_RELOC(R_HEX_GD_GOT_HI16, 51)
+ELF_RELOC(R_HEX_GD_GOT_32, 52)
+ELF_RELOC(R_HEX_GD_GOT_16, 53)
+ELF_RELOC(R_HEX_IE_LO16, 54)
+ELF_RELOC(R_HEX_IE_HI16, 55)
+ELF_RELOC(R_HEX_IE_32, 56)
+ELF_RELOC(R_HEX_IE_GOT_LO16, 57)
+ELF_RELOC(R_HEX_IE_GOT_HI16, 58)
+ELF_RELOC(R_HEX_IE_GOT_32, 59)
+ELF_RELOC(R_HEX_IE_GOT_16, 60)
+ELF_RELOC(R_HEX_TPREL_LO16, 61)
+ELF_RELOC(R_HEX_TPREL_HI16, 62)
+ELF_RELOC(R_HEX_TPREL_32, 63)
+ELF_RELOC(R_HEX_TPREL_16, 64)
+ELF_RELOC(R_HEX_6_PCREL_X, 65)
+ELF_RELOC(R_HEX_GOTREL_32_6_X, 66)
+ELF_RELOC(R_HEX_GOTREL_16_X, 67)
+ELF_RELOC(R_HEX_GOTREL_11_X, 68)
+ELF_RELOC(R_HEX_GOT_32_6_X, 69)
+ELF_RELOC(R_HEX_GOT_16_X, 70)
+ELF_RELOC(R_HEX_GOT_11_X, 71)
+ELF_RELOC(R_HEX_DTPREL_32_6_X, 72)
+ELF_RELOC(R_HEX_DTPREL_16_X, 73)
+ELF_RELOC(R_HEX_DTPREL_11_X, 74)
+ELF_RELOC(R_HEX_GD_GOT_32_6_X, 75)
+ELF_RELOC(R_HEX_GD_GOT_16_X, 76)
+ELF_RELOC(R_HEX_GD_GOT_11_X, 77)
+ELF_RELOC(R_HEX_IE_32_6_X, 78)
+ELF_RELOC(R_HEX_IE_16_X, 79)
+ELF_RELOC(R_HEX_IE_GOT_32_6_X, 80)
+ELF_RELOC(R_HEX_IE_GOT_16_X, 81)
+ELF_RELOC(R_HEX_IE_GOT_11_X, 82)
+ELF_RELOC(R_HEX_TPREL_32_6_X, 83)
+ELF_RELOC(R_HEX_TPREL_16_X, 84)
+ELF_RELOC(R_HEX_TPREL_11_X, 85)
diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def
new file mode 100644
index 0000000..dc57346
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Mips.def
@@ -0,0 +1,112 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_MIPS_NONE, 0)
+ELF_RELOC(R_MIPS_16, 1)
+ELF_RELOC(R_MIPS_32, 2)
+ELF_RELOC(R_MIPS_REL32, 3)
+ELF_RELOC(R_MIPS_26, 4)
+ELF_RELOC(R_MIPS_HI16, 5)
+ELF_RELOC(R_MIPS_LO16, 6)
+ELF_RELOC(R_MIPS_GPREL16, 7)
+ELF_RELOC(R_MIPS_LITERAL, 8)
+ELF_RELOC(R_MIPS_GOT16, 9)
+ELF_RELOC(R_MIPS_PC16, 10)
+ELF_RELOC(R_MIPS_CALL16, 11)
+ELF_RELOC(R_MIPS_GPREL32, 12)
+ELF_RELOC(R_MIPS_UNUSED1, 13)
+ELF_RELOC(R_MIPS_UNUSED2, 14)
+ELF_RELOC(R_MIPS_UNUSED3, 15)
+ELF_RELOC(R_MIPS_SHIFT5, 16)
+ELF_RELOC(R_MIPS_SHIFT6, 17)
+ELF_RELOC(R_MIPS_64, 18)
+ELF_RELOC(R_MIPS_GOT_DISP, 19)
+ELF_RELOC(R_MIPS_GOT_PAGE, 20)
+ELF_RELOC(R_MIPS_GOT_OFST, 21)
+ELF_RELOC(R_MIPS_GOT_HI16, 22)
+ELF_RELOC(R_MIPS_GOT_LO16, 23)
+ELF_RELOC(R_MIPS_SUB, 24)
+ELF_RELOC(R_MIPS_INSERT_A, 25)
+ELF_RELOC(R_MIPS_INSERT_B, 26)
+ELF_RELOC(R_MIPS_DELETE, 27)
+ELF_RELOC(R_MIPS_HIGHER, 28)
+ELF_RELOC(R_MIPS_HIGHEST, 29)
+ELF_RELOC(R_MIPS_CALL_HI16, 30)
+ELF_RELOC(R_MIPS_CALL_LO16, 31)
+ELF_RELOC(R_MIPS_SCN_DISP, 32)
+ELF_RELOC(R_MIPS_REL16, 33)
+ELF_RELOC(R_MIPS_ADD_IMMEDIATE, 34)
+ELF_RELOC(R_MIPS_PJUMP, 35)
+ELF_RELOC(R_MIPS_RELGOT, 36)
+ELF_RELOC(R_MIPS_JALR, 37)
+ELF_RELOC(R_MIPS_TLS_DTPMOD32, 38)
+ELF_RELOC(R_MIPS_TLS_DTPREL32, 39)
+ELF_RELOC(R_MIPS_TLS_DTPMOD64, 40)
+ELF_RELOC(R_MIPS_TLS_DTPREL64, 41)
+ELF_RELOC(R_MIPS_TLS_GD, 42)
+ELF_RELOC(R_MIPS_TLS_LDM, 43)
+ELF_RELOC(R_MIPS_TLS_DTPREL_HI16, 44)
+ELF_RELOC(R_MIPS_TLS_DTPREL_LO16, 45)
+ELF_RELOC(R_MIPS_TLS_GOTTPREL, 46)
+ELF_RELOC(R_MIPS_TLS_TPREL32, 47)
+ELF_RELOC(R_MIPS_TLS_TPREL64, 48)
+ELF_RELOC(R_MIPS_TLS_TPREL_HI16, 49)
+ELF_RELOC(R_MIPS_TLS_TPREL_LO16, 50)
+ELF_RELOC(R_MIPS_GLOB_DAT, 51)
+ELF_RELOC(R_MIPS_PC21_S2, 60)
+ELF_RELOC(R_MIPS_PC26_S2, 61)
+ELF_RELOC(R_MIPS_PC18_S3, 62)
+ELF_RELOC(R_MIPS_PC19_S2, 63)
+ELF_RELOC(R_MIPS_PCHI16, 64)
+ELF_RELOC(R_MIPS_PCLO16, 65)
+ELF_RELOC(R_MIPS16_26, 100)
+ELF_RELOC(R_MIPS16_GPREL, 101)
+ELF_RELOC(R_MIPS16_GOT16, 102)
+ELF_RELOC(R_MIPS16_CALL16, 103)
+ELF_RELOC(R_MIPS16_HI16, 104)
+ELF_RELOC(R_MIPS16_LO16, 105)
+ELF_RELOC(R_MIPS16_TLS_GD, 106)
+ELF_RELOC(R_MIPS16_TLS_LDM, 107)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_HI16, 108)
+ELF_RELOC(R_MIPS16_TLS_DTPREL_LO16, 109)
+ELF_RELOC(R_MIPS16_TLS_GOTTPREL, 110)
+ELF_RELOC(R_MIPS16_TLS_TPREL_HI16, 111)
+ELF_RELOC(R_MIPS16_TLS_TPREL_LO16, 112)
+ELF_RELOC(R_MIPS_COPY, 126)
+ELF_RELOC(R_MIPS_JUMP_SLOT, 127)
+ELF_RELOC(R_MICROMIPS_26_S1, 133)
+ELF_RELOC(R_MICROMIPS_HI16, 134)
+ELF_RELOC(R_MICROMIPS_LO16, 135)
+ELF_RELOC(R_MICROMIPS_GPREL16, 136)
+ELF_RELOC(R_MICROMIPS_LITERAL, 137)
+ELF_RELOC(R_MICROMIPS_GOT16, 138)
+ELF_RELOC(R_MICROMIPS_PC7_S1, 139)
+ELF_RELOC(R_MICROMIPS_PC10_S1, 140)
+ELF_RELOC(R_MICROMIPS_PC16_S1, 141)
+ELF_RELOC(R_MICROMIPS_CALL16, 142)
+ELF_RELOC(R_MICROMIPS_GOT_DISP, 145)
+ELF_RELOC(R_MICROMIPS_GOT_PAGE, 146)
+ELF_RELOC(R_MICROMIPS_GOT_OFST, 147)
+ELF_RELOC(R_MICROMIPS_GOT_HI16, 148)
+ELF_RELOC(R_MICROMIPS_GOT_LO16, 149)
+ELF_RELOC(R_MICROMIPS_SUB, 150)
+ELF_RELOC(R_MICROMIPS_HIGHER, 151)
+ELF_RELOC(R_MICROMIPS_HIGHEST, 152)
+ELF_RELOC(R_MICROMIPS_CALL_HI16, 153)
+ELF_RELOC(R_MICROMIPS_CALL_LO16, 154)
+ELF_RELOC(R_MICROMIPS_SCN_DISP, 155)
+ELF_RELOC(R_MICROMIPS_JALR, 156)
+ELF_RELOC(R_MICROMIPS_HI0_LO16, 157)
+ELF_RELOC(R_MICROMIPS_TLS_GD, 162)
+ELF_RELOC(R_MICROMIPS_TLS_LDM, 163)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_HI16, 164)
+ELF_RELOC(R_MICROMIPS_TLS_DTPREL_LO16, 165)
+ELF_RELOC(R_MICROMIPS_TLS_GOTTPREL, 166)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169)
+ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170)
+ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172)
+ELF_RELOC(R_MICROMIPS_PC23_S2, 173)
+ELF_RELOC(R_MIPS_NUM, 218)
+ELF_RELOC(R_MIPS_PC32, 248)
diff --git a/include/llvm/Support/ELFRelocs/PowerPC.def b/include/llvm/Support/ELFRelocs/PowerPC.def
new file mode 100644
index 0000000..b6c3941
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/PowerPC.def
@@ -0,0 +1,61 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_PPC_NONE, 0) /* No relocation. */
+ELF_RELOC(R_PPC_ADDR32, 1)
+ELF_RELOC(R_PPC_ADDR24, 2)
+ELF_RELOC(R_PPC_ADDR16, 3)
+ELF_RELOC(R_PPC_ADDR16_LO, 4)
+ELF_RELOC(R_PPC_ADDR16_HI, 5)
+ELF_RELOC(R_PPC_ADDR16_HA, 6)
+ELF_RELOC(R_PPC_ADDR14, 7)
+ELF_RELOC(R_PPC_ADDR14_BRTAKEN, 8)
+ELF_RELOC(R_PPC_ADDR14_BRNTAKEN, 9)
+ELF_RELOC(R_PPC_REL24, 10)
+ELF_RELOC(R_PPC_REL14, 11)
+ELF_RELOC(R_PPC_REL14_BRTAKEN, 12)
+ELF_RELOC(R_PPC_REL14_BRNTAKEN, 13)
+ELF_RELOC(R_PPC_GOT16, 14)
+ELF_RELOC(R_PPC_GOT16_LO, 15)
+ELF_RELOC(R_PPC_GOT16_HI, 16)
+ELF_RELOC(R_PPC_GOT16_HA, 17)
+ELF_RELOC(R_PPC_PLTREL24, 18)
+ELF_RELOC(R_PPC_JMP_SLOT, 21)
+ELF_RELOC(R_PPC_LOCAL24PC, 23)
+ELF_RELOC(R_PPC_REL32, 26)
+ELF_RELOC(R_PPC_TLS, 67)
+ELF_RELOC(R_PPC_DTPMOD32, 68)
+ELF_RELOC(R_PPC_TPREL16, 69)
+ELF_RELOC(R_PPC_TPREL16_LO, 70)
+ELF_RELOC(R_PPC_TPREL16_HI, 71)
+ELF_RELOC(R_PPC_TPREL16_HA, 72)
+ELF_RELOC(R_PPC_TPREL32, 73)
+ELF_RELOC(R_PPC_DTPREL16, 74)
+ELF_RELOC(R_PPC_DTPREL16_LO, 75)
+ELF_RELOC(R_PPC_DTPREL16_HI, 76)
+ELF_RELOC(R_PPC_DTPREL16_HA, 77)
+ELF_RELOC(R_PPC_DTPREL32, 78)
+ELF_RELOC(R_PPC_GOT_TLSGD16, 79)
+ELF_RELOC(R_PPC_GOT_TLSGD16_LO, 80)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HI, 81)
+ELF_RELOC(R_PPC_GOT_TLSGD16_HA, 82)
+ELF_RELOC(R_PPC_GOT_TLSLD16, 83)
+ELF_RELOC(R_PPC_GOT_TLSLD16_LO, 84)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HI, 85)
+ELF_RELOC(R_PPC_GOT_TLSLD16_HA, 86)
+ELF_RELOC(R_PPC_GOT_TPREL16, 87)
+ELF_RELOC(R_PPC_GOT_TPREL16_LO, 88)
+ELF_RELOC(R_PPC_GOT_TPREL16_HI, 89)
+ELF_RELOC(R_PPC_GOT_TPREL16_HA, 90)
+ELF_RELOC(R_PPC_GOT_DTPREL16, 91)
+ELF_RELOC(R_PPC_GOT_DTPREL16_LO, 92)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HI, 93)
+ELF_RELOC(R_PPC_GOT_DTPREL16_HA, 94)
+ELF_RELOC(R_PPC_TLSGD, 95)
+ELF_RELOC(R_PPC_TLSLD, 96)
+ELF_RELOC(R_PPC_REL16, 249)
+ELF_RELOC(R_PPC_REL16_LO, 250)
+ELF_RELOC(R_PPC_REL16_HI, 251)
+ELF_RELOC(R_PPC_REL16_HA, 252)
diff --git a/include/llvm/Support/ELFRelocs/PowerPC64.def b/include/llvm/Support/ELFRelocs/PowerPC64.def
new file mode 100644
index 0000000..7b2a3cb
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/PowerPC64.def
@@ -0,0 +1,88 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_PPC64_NONE, 0)
+ELF_RELOC(R_PPC64_ADDR32, 1)
+ELF_RELOC(R_PPC64_ADDR24, 2)
+ELF_RELOC(R_PPC64_ADDR16, 3)
+ELF_RELOC(R_PPC64_ADDR16_LO, 4)
+ELF_RELOC(R_PPC64_ADDR16_HI, 5)
+ELF_RELOC(R_PPC64_ADDR16_HA, 6)
+ELF_RELOC(R_PPC64_ADDR14, 7)
+ELF_RELOC(R_PPC64_ADDR14_BRTAKEN, 8)
+ELF_RELOC(R_PPC64_ADDR14_BRNTAKEN, 9)
+ELF_RELOC(R_PPC64_REL24, 10)
+ELF_RELOC(R_PPC64_REL14, 11)
+ELF_RELOC(R_PPC64_REL14_BRTAKEN, 12)
+ELF_RELOC(R_PPC64_REL14_BRNTAKEN, 13)
+ELF_RELOC(R_PPC64_GOT16, 14)
+ELF_RELOC(R_PPC64_GOT16_LO, 15)
+ELF_RELOC(R_PPC64_GOT16_HI, 16)
+ELF_RELOC(R_PPC64_GOT16_HA, 17)
+ELF_RELOC(R_PPC64_JMP_SLOT, 21)
+ELF_RELOC(R_PPC64_REL32, 26)
+ELF_RELOC(R_PPC64_ADDR64, 38)
+ELF_RELOC(R_PPC64_ADDR16_HIGHER, 39)
+ELF_RELOC(R_PPC64_ADDR16_HIGHERA, 40)
+ELF_RELOC(R_PPC64_ADDR16_HIGHEST, 41)
+ELF_RELOC(R_PPC64_ADDR16_HIGHESTA, 42)
+ELF_RELOC(R_PPC64_REL64, 44)
+ELF_RELOC(R_PPC64_TOC16, 47)
+ELF_RELOC(R_PPC64_TOC16_LO, 48)
+ELF_RELOC(R_PPC64_TOC16_HI, 49)
+ELF_RELOC(R_PPC64_TOC16_HA, 50)
+ELF_RELOC(R_PPC64_TOC, 51)
+ELF_RELOC(R_PPC64_ADDR16_DS, 56)
+ELF_RELOC(R_PPC64_ADDR16_LO_DS, 57)
+ELF_RELOC(R_PPC64_GOT16_DS, 58)
+ELF_RELOC(R_PPC64_GOT16_LO_DS, 59)
+ELF_RELOC(R_PPC64_TOC16_DS, 63)
+ELF_RELOC(R_PPC64_TOC16_LO_DS, 64)
+ELF_RELOC(R_PPC64_TLS, 67)
+ELF_RELOC(R_PPC64_DTPMOD64, 68)
+ELF_RELOC(R_PPC64_TPREL16, 69)
+ELF_RELOC(R_PPC64_TPREL16_LO, 70)
+ELF_RELOC(R_PPC64_TPREL16_HI, 71)
+ELF_RELOC(R_PPC64_TPREL16_HA, 72)
+ELF_RELOC(R_PPC64_TPREL64, 73)
+ELF_RELOC(R_PPC64_DTPREL16, 74)
+ELF_RELOC(R_PPC64_DTPREL16_LO, 75)
+ELF_RELOC(R_PPC64_DTPREL16_HI, 76)
+ELF_RELOC(R_PPC64_DTPREL16_HA, 77)
+ELF_RELOC(R_PPC64_DTPREL64, 78)
+ELF_RELOC(R_PPC64_GOT_TLSGD16, 79)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_LO, 80)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HI, 81)
+ELF_RELOC(R_PPC64_GOT_TLSGD16_HA, 82)
+ELF_RELOC(R_PPC64_GOT_TLSLD16, 83)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_LO, 84)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HI, 85)
+ELF_RELOC(R_PPC64_GOT_TLSLD16_HA, 86)
+ELF_RELOC(R_PPC64_GOT_TPREL16_DS, 87)
+ELF_RELOC(R_PPC64_GOT_TPREL16_LO_DS, 88)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HI, 89)
+ELF_RELOC(R_PPC64_GOT_TPREL16_HA, 90)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_DS, 91)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_LO_DS, 92)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HI, 93)
+ELF_RELOC(R_PPC64_GOT_DTPREL16_HA, 94)
+ELF_RELOC(R_PPC64_TPREL16_DS, 95)
+ELF_RELOC(R_PPC64_TPREL16_LO_DS, 96)
+ELF_RELOC(R_PPC64_TPREL16_HIGHER, 97)
+ELF_RELOC(R_PPC64_TPREL16_HIGHERA, 98)
+ELF_RELOC(R_PPC64_TPREL16_HIGHEST, 99)
+ELF_RELOC(R_PPC64_TPREL16_HIGHESTA, 100)
+ELF_RELOC(R_PPC64_DTPREL16_DS, 101)
+ELF_RELOC(R_PPC64_DTPREL16_LO_DS, 102)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHER, 103)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHERA, 104)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHEST, 105)
+ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106)
+ELF_RELOC(R_PPC64_TLSGD, 107)
+ELF_RELOC(R_PPC64_TLSLD, 108)
+ELF_RELOC(R_PPC64_REL16, 249)
+ELF_RELOC(R_PPC64_REL16_LO, 250)
+ELF_RELOC(R_PPC64_REL16_HI, 251)
+ELF_RELOC(R_PPC64_REL16_HA, 252)
diff --git a/include/llvm/Support/ELFRelocs/Sparc.def b/include/llvm/Support/ELFRelocs/Sparc.def
new file mode 100644
index 0000000..d6772ea
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/Sparc.def
@@ -0,0 +1,89 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_SPARC_NONE, 0)
+ELF_RELOC(R_SPARC_8, 1)
+ELF_RELOC(R_SPARC_16, 2)
+ELF_RELOC(R_SPARC_32, 3)
+ELF_RELOC(R_SPARC_DISP8, 4)
+ELF_RELOC(R_SPARC_DISP16, 5)
+ELF_RELOC(R_SPARC_DISP32, 6)
+ELF_RELOC(R_SPARC_WDISP30, 7)
+ELF_RELOC(R_SPARC_WDISP22, 8)
+ELF_RELOC(R_SPARC_HI22, 9)
+ELF_RELOC(R_SPARC_22, 10)
+ELF_RELOC(R_SPARC_13, 11)
+ELF_RELOC(R_SPARC_LO10, 12)
+ELF_RELOC(R_SPARC_GOT10, 13)
+ELF_RELOC(R_SPARC_GOT13, 14)
+ELF_RELOC(R_SPARC_GOT22, 15)
+ELF_RELOC(R_SPARC_PC10, 16)
+ELF_RELOC(R_SPARC_PC22, 17)
+ELF_RELOC(R_SPARC_WPLT30, 18)
+ELF_RELOC(R_SPARC_COPY, 19)
+ELF_RELOC(R_SPARC_GLOB_DAT, 20)
+ELF_RELOC(R_SPARC_JMP_SLOT, 21)
+ELF_RELOC(R_SPARC_RELATIVE, 22)
+ELF_RELOC(R_SPARC_UA32, 23)
+ELF_RELOC(R_SPARC_PLT32, 24)
+ELF_RELOC(R_SPARC_HIPLT22, 25)
+ELF_RELOC(R_SPARC_LOPLT10, 26)
+ELF_RELOC(R_SPARC_PCPLT32, 27)
+ELF_RELOC(R_SPARC_PCPLT22, 28)
+ELF_RELOC(R_SPARC_PCPLT10, 29)
+ELF_RELOC(R_SPARC_10, 30)
+ELF_RELOC(R_SPARC_11, 31)
+ELF_RELOC(R_SPARC_64, 32)
+ELF_RELOC(R_SPARC_OLO10, 33)
+ELF_RELOC(R_SPARC_HH22, 34)
+ELF_RELOC(R_SPARC_HM10, 35)
+ELF_RELOC(R_SPARC_LM22, 36)
+ELF_RELOC(R_SPARC_PC_HH22, 37)
+ELF_RELOC(R_SPARC_PC_HM10, 38)
+ELF_RELOC(R_SPARC_PC_LM22, 39)
+ELF_RELOC(R_SPARC_WDISP16, 40)
+ELF_RELOC(R_SPARC_WDISP19, 41)
+ELF_RELOC(R_SPARC_7, 43)
+ELF_RELOC(R_SPARC_5, 44)
+ELF_RELOC(R_SPARC_6, 45)
+ELF_RELOC(R_SPARC_DISP64, 46)
+ELF_RELOC(R_SPARC_PLT64, 47)
+ELF_RELOC(R_SPARC_HIX22, 48)
+ELF_RELOC(R_SPARC_LOX10, 49)
+ELF_RELOC(R_SPARC_H44, 50)
+ELF_RELOC(R_SPARC_M44, 51)
+ELF_RELOC(R_SPARC_L44, 52)
+ELF_RELOC(R_SPARC_REGISTER, 53)
+ELF_RELOC(R_SPARC_UA64, 54)
+ELF_RELOC(R_SPARC_UA16, 55)
+ELF_RELOC(R_SPARC_TLS_GD_HI22, 56)
+ELF_RELOC(R_SPARC_TLS_GD_LO10, 57)
+ELF_RELOC(R_SPARC_TLS_GD_ADD, 58)
+ELF_RELOC(R_SPARC_TLS_GD_CALL, 59)
+ELF_RELOC(R_SPARC_TLS_LDM_HI22, 60)
+ELF_RELOC(R_SPARC_TLS_LDM_LO10, 61)
+ELF_RELOC(R_SPARC_TLS_LDM_ADD, 62)
+ELF_RELOC(R_SPARC_TLS_LDM_CALL, 63)
+ELF_RELOC(R_SPARC_TLS_LDO_HIX22, 64)
+ELF_RELOC(R_SPARC_TLS_LDO_LOX10, 65)
+ELF_RELOC(R_SPARC_TLS_LDO_ADD, 66)
+ELF_RELOC(R_SPARC_TLS_IE_HI22, 67)
+ELF_RELOC(R_SPARC_TLS_IE_LO10, 68)
+ELF_RELOC(R_SPARC_TLS_IE_LD, 69)
+ELF_RELOC(R_SPARC_TLS_IE_LDX, 70)
+ELF_RELOC(R_SPARC_TLS_IE_ADD, 71)
+ELF_RELOC(R_SPARC_TLS_LE_HIX22, 72)
+ELF_RELOC(R_SPARC_TLS_LE_LOX10, 73)
+ELF_RELOC(R_SPARC_TLS_DTPMOD32, 74)
+ELF_RELOC(R_SPARC_TLS_DTPMOD64, 75)
+ELF_RELOC(R_SPARC_TLS_DTPOFF32, 76)
+ELF_RELOC(R_SPARC_TLS_DTPOFF64, 77)
+ELF_RELOC(R_SPARC_TLS_TPOFF32, 78)
+ELF_RELOC(R_SPARC_TLS_TPOFF64, 79)
+ELF_RELOC(R_SPARC_GOTDATA_HIX22, 80)
+ELF_RELOC(R_SPARC_GOTDATA_LOX22, 81)
+ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82)
+ELF_RELOC(R_SPARC_GOTDATA_OP_LOX22, 83)
+ELF_RELOC(R_SPARC_GOTDATA_OP, 84)
diff --git a/include/llvm/Support/ELFRelocs/SystemZ.def b/include/llvm/Support/ELFRelocs/SystemZ.def
new file mode 100644
index 0000000..711f940
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/SystemZ.def
@@ -0,0 +1,67 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_390_NONE, 0)
+ELF_RELOC(R_390_8, 1)
+ELF_RELOC(R_390_12, 2)
+ELF_RELOC(R_390_16, 3)
+ELF_RELOC(R_390_32, 4)
+ELF_RELOC(R_390_PC32, 5)
+ELF_RELOC(R_390_GOT12, 6)
+ELF_RELOC(R_390_GOT32, 7)
+ELF_RELOC(R_390_PLT32, 8)
+ELF_RELOC(R_390_COPY, 9)
+ELF_RELOC(R_390_GLOB_DAT, 10)
+ELF_RELOC(R_390_JMP_SLOT, 11)
+ELF_RELOC(R_390_RELATIVE, 12)
+ELF_RELOC(R_390_GOTOFF, 13)
+ELF_RELOC(R_390_GOTPC, 14)
+ELF_RELOC(R_390_GOT16, 15)
+ELF_RELOC(R_390_PC16, 16)
+ELF_RELOC(R_390_PC16DBL, 17)
+ELF_RELOC(R_390_PLT16DBL, 18)
+ELF_RELOC(R_390_PC32DBL, 19)
+ELF_RELOC(R_390_PLT32DBL, 20)
+ELF_RELOC(R_390_GOTPCDBL, 21)
+ELF_RELOC(R_390_64, 22)
+ELF_RELOC(R_390_PC64, 23)
+ELF_RELOC(R_390_GOT64, 24)
+ELF_RELOC(R_390_PLT64, 25)
+ELF_RELOC(R_390_GOTENT, 26)
+ELF_RELOC(R_390_GOTOFF16, 27)
+ELF_RELOC(R_390_GOTOFF64, 28)
+ELF_RELOC(R_390_GOTPLT12, 29)
+ELF_RELOC(R_390_GOTPLT16, 30)
+ELF_RELOC(R_390_GOTPLT32, 31)
+ELF_RELOC(R_390_GOTPLT64, 32)
+ELF_RELOC(R_390_GOTPLTENT, 33)
+ELF_RELOC(R_390_PLTOFF16, 34)
+ELF_RELOC(R_390_PLTOFF32, 35)
+ELF_RELOC(R_390_PLTOFF64, 36)
+ELF_RELOC(R_390_TLS_LOAD, 37)
+ELF_RELOC(R_390_TLS_GDCALL, 38)
+ELF_RELOC(R_390_TLS_LDCALL, 39)
+ELF_RELOC(R_390_TLS_GD32, 40)
+ELF_RELOC(R_390_TLS_GD64, 41)
+ELF_RELOC(R_390_TLS_GOTIE12, 42)
+ELF_RELOC(R_390_TLS_GOTIE32, 43)
+ELF_RELOC(R_390_TLS_GOTIE64, 44)
+ELF_RELOC(R_390_TLS_LDM32, 45)
+ELF_RELOC(R_390_TLS_LDM64, 46)
+ELF_RELOC(R_390_TLS_IE32, 47)
+ELF_RELOC(R_390_TLS_IE64, 48)
+ELF_RELOC(R_390_TLS_IEENT, 49)
+ELF_RELOC(R_390_TLS_LE32, 50)
+ELF_RELOC(R_390_TLS_LE64, 51)
+ELF_RELOC(R_390_TLS_LDO32, 52)
+ELF_RELOC(R_390_TLS_LDO64, 53)
+ELF_RELOC(R_390_TLS_DTPMOD, 54)
+ELF_RELOC(R_390_TLS_DTPOFF, 55)
+ELF_RELOC(R_390_TLS_TPOFF, 56)
+ELF_RELOC(R_390_20, 57)
+ELF_RELOC(R_390_GOT20, 58)
+ELF_RELOC(R_390_GOTPLT20, 59)
+ELF_RELOC(R_390_TLS_GOTIE20, 60)
+ELF_RELOC(R_390_IRELATIVE, 61)
diff --git a/include/llvm/Support/ELFRelocs/i386.def b/include/llvm/Support/ELFRelocs/i386.def
new file mode 100644
index 0000000..45eae7f
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/i386.def
@@ -0,0 +1,47 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// TODO: this is just a subset
+ELF_RELOC(R_386_NONE, 0)
+ELF_RELOC(R_386_32, 1)
+ELF_RELOC(R_386_PC32, 2)
+ELF_RELOC(R_386_GOT32, 3)
+ELF_RELOC(R_386_PLT32, 4)
+ELF_RELOC(R_386_COPY, 5)
+ELF_RELOC(R_386_GLOB_DAT, 6)
+ELF_RELOC(R_386_JUMP_SLOT, 7)
+ELF_RELOC(R_386_RELATIVE, 8)
+ELF_RELOC(R_386_GOTOFF, 9)
+ELF_RELOC(R_386_GOTPC, 10)
+ELF_RELOC(R_386_32PLT, 11)
+ELF_RELOC(R_386_TLS_TPOFF, 14)
+ELF_RELOC(R_386_TLS_IE, 15)
+ELF_RELOC(R_386_TLS_GOTIE, 16)
+ELF_RELOC(R_386_TLS_LE, 17)
+ELF_RELOC(R_386_TLS_GD, 18)
+ELF_RELOC(R_386_TLS_LDM, 19)
+ELF_RELOC(R_386_16, 20)
+ELF_RELOC(R_386_PC16, 21)
+ELF_RELOC(R_386_8, 22)
+ELF_RELOC(R_386_PC8, 23)
+ELF_RELOC(R_386_TLS_GD_32, 24)
+ELF_RELOC(R_386_TLS_GD_PUSH, 25)
+ELF_RELOC(R_386_TLS_GD_CALL, 26)
+ELF_RELOC(R_386_TLS_GD_POP, 27)
+ELF_RELOC(R_386_TLS_LDM_32, 28)
+ELF_RELOC(R_386_TLS_LDM_PUSH, 29)
+ELF_RELOC(R_386_TLS_LDM_CALL, 30)
+ELF_RELOC(R_386_TLS_LDM_POP, 31)
+ELF_RELOC(R_386_TLS_LDO_32, 32)
+ELF_RELOC(R_386_TLS_IE_32, 33)
+ELF_RELOC(R_386_TLS_LE_32, 34)
+ELF_RELOC(R_386_TLS_DTPMOD32, 35)
+ELF_RELOC(R_386_TLS_DTPOFF32, 36)
+ELF_RELOC(R_386_TLS_TPOFF32, 37)
+ELF_RELOC(R_386_TLS_GOTDESC, 39)
+ELF_RELOC(R_386_TLS_DESC_CALL, 40)
+ELF_RELOC(R_386_TLS_DESC, 41)
+ELF_RELOC(R_386_IRELATIVE, 42)
+ELF_RELOC(R_386_NUM, 43)
diff --git a/include/llvm/Support/ELFRelocs/x86_64.def b/include/llvm/Support/ELFRelocs/x86_64.def
new file mode 100644
index 0000000..36ad061
--- /dev/null
+++ b/include/llvm/Support/ELFRelocs/x86_64.def
@@ -0,0 +1,44 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_X86_64_NONE, 0)
+ELF_RELOC(R_X86_64_64, 1)
+ELF_RELOC(R_X86_64_PC32, 2)
+ELF_RELOC(R_X86_64_GOT32, 3)
+ELF_RELOC(R_X86_64_PLT32, 4)
+ELF_RELOC(R_X86_64_COPY, 5)
+ELF_RELOC(R_X86_64_GLOB_DAT, 6)
+ELF_RELOC(R_X86_64_JUMP_SLOT, 7)
+ELF_RELOC(R_X86_64_RELATIVE, 8)
+ELF_RELOC(R_X86_64_GOTPCREL, 9)
+ELF_RELOC(R_X86_64_32, 10)
+ELF_RELOC(R_X86_64_32S, 11)
+ELF_RELOC(R_X86_64_16, 12)
+ELF_RELOC(R_X86_64_PC16, 13)
+ELF_RELOC(R_X86_64_8, 14)
+ELF_RELOC(R_X86_64_PC8, 15)
+ELF_RELOC(R_X86_64_DTPMOD64, 16)
+ELF_RELOC(R_X86_64_DTPOFF64, 17)
+ELF_RELOC(R_X86_64_TPOFF64, 18)
+ELF_RELOC(R_X86_64_TLSGD, 19)
+ELF_RELOC(R_X86_64_TLSLD, 20)
+ELF_RELOC(R_X86_64_DTPOFF32, 21)
+ELF_RELOC(R_X86_64_GOTTPOFF, 22)
+ELF_RELOC(R_X86_64_TPOFF32, 23)
+ELF_RELOC(R_X86_64_PC64, 24)
+ELF_RELOC(R_X86_64_GOTOFF64, 25)
+ELF_RELOC(R_X86_64_GOTPC32, 26)
+ELF_RELOC(R_X86_64_GOT64, 27)
+ELF_RELOC(R_X86_64_GOTPCREL64, 28)
+ELF_RELOC(R_X86_64_GOTPC64, 29)
+ELF_RELOC(R_X86_64_GOTPLT64, 30)
+ELF_RELOC(R_X86_64_PLTOFF64, 31)
+ELF_RELOC(R_X86_64_SIZE32, 32)
+ELF_RELOC(R_X86_64_SIZE64, 33)
+ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34)
+ELF_RELOC(R_X86_64_TLSDESC_CALL, 35)
+ELF_RELOC(R_X86_64_TLSDESC, 36)
+ELF_RELOC(R_X86_64_IRELATIVE, 37)
+
diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h
index 94f372f..d44a9b3 100644
--- a/include/llvm/Support/EndianStream.h
+++ b/include/llvm/Support/EndianStream.h
@@ -31,6 +31,31 @@ template <endianness endian> struct Writer {
OS.write((const char *)&Val, sizeof(value_type));
}
};
+
+template <>
+template <>
+inline void Writer<little>::write<float>(float Val) {
+ write(FloatToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<little>::write<double>(double Val) {
+ write(DoubleToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<big>::write<float>(float Val) {
+ write(FloatToBits(Val));
+}
+
+template <>
+template <>
+inline void Writer<big>::write<double>(double Val) {
+ write(DoubleToBits(Val));
+}
+
} // end namespace endian
} // end namespace support
diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h
index 84763de..3577a12 100644
--- a/include/llvm/Support/ErrorOr.h
+++ b/include/llvm/Support/ErrorOr.h
@@ -168,7 +168,7 @@ public:
}
/// \brief Return false if there is an error.
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return !HasError;
}
diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h
index a7cfacd..fd8879c 100644
--- a/include/llvm/Support/FileOutputBuffer.h
+++ b/include/llvm/Support/FileOutputBuffer.h
@@ -66,7 +66,7 @@ public:
/// is called, the file is deleted in the destructor. The optional parameter
/// is used if it turns out you want the file size to be smaller than
/// initially requested.
- std::error_code commit(int64_t NewSmallerSize = -1);
+ std::error_code commit();
/// If this object was previously committed, the destructor just deletes
/// this object. If this object was not committed, the destructor
@@ -74,8 +74,8 @@ public:
~FileOutputBuffer();
private:
- FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
- FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION;
+ FileOutputBuffer(const FileOutputBuffer &) = delete;
+ FileOutputBuffer &operator=(const FileOutputBuffer &) = delete;
FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R,
StringRef Path, StringRef TempPath);
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index 63c9ed5..b3b44c4 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -241,6 +241,7 @@ struct file_magic {
macho_bundle, ///< Mach-O Bundle file
macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub
macho_dsym_companion, ///< Mach-O dSYM companion file
+ macho_kext_bundle, ///< Mach-O kext bundle file
macho_universal_binary, ///< Mach-O universal binary
coff_object, ///< COFF object file
coff_import_library, ///< COFF import library
@@ -336,11 +337,11 @@ std::error_code copy_file(const Twine &From, const Twine &To);
/// @brief Resize path to size. File is resized as if by POSIX truncate().
///
-/// @param path Input path.
-/// @param size Size to resize to.
+/// @param FD Input file descriptor.
+/// @param Size Size to resize to.
/// @returns errc::success if \a path has been resized to \a size, otherwise a
/// platform-specific error_code.
-std::error_code resize_file(const Twine &path, uint64_t size);
+std::error_code resize_file(int FD, uint64_t Size);
/// @}
/// @name Physical Observers
@@ -624,9 +625,9 @@ std::error_code getUniqueID(const Twine Path, UniqueID &Result);
/// This class represents a memory mapped file. It is based on
/// boost::iostreams::mapped_file.
class mapped_file_region {
- mapped_file_region() LLVM_DELETED_FUNCTION;
- mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION;
- mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION;
+ mapped_file_region() = delete;
+ mapped_file_region(mapped_file_region&) = delete;
+ mapped_file_region &operator =(mapped_file_region&) = delete;
public:
enum mapmode {
@@ -637,49 +638,20 @@ public:
private:
/// Platform-specific mapping state.
- mapmode Mode;
uint64_t Size;
void *Mapping;
-#ifdef LLVM_ON_WIN32
- int FileDescriptor;
- void *FileHandle;
- void *FileMappingHandle;
-#endif
- std::error_code init(int FD, bool CloseFD, uint64_t Offset);
+ std::error_code init(int FD, uint64_t Offset, mapmode Mode);
public:
- typedef char char_type;
-
- mapped_file_region(mapped_file_region&&);
- mapped_file_region &operator =(mapped_file_region&&);
-
- /// Construct a mapped_file_region at \a path starting at \a offset of length
- /// \a length and with access \a mode.
- ///
- /// \param path Path to the file to map. If it does not exist it will be
- /// created.
- /// \param mode How to map the memory.
- /// \param length Number of bytes to map in starting at \a offset. If the file
- /// is shorter than this, it will be extended. If \a length is
- /// 0, the entire file will be mapped.
- /// \param offset Byte offset from the beginning of the file where the map
- /// should begin. Must be a multiple of
- /// mapped_file_region::alignment().
- /// \param ec This is set to errc::success if the map was constructed
- /// successfully. Otherwise it is set to a platform dependent error.
- mapped_file_region(const Twine &path, mapmode mode, uint64_t length,
- uint64_t offset, std::error_code &ec);
-
/// \param fd An open file descriptor to map. mapped_file_region takes
/// ownership if closefd is true. It must have been opended in the correct
/// mode.
- mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length,
- uint64_t offset, std::error_code &ec);
+ mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset,
+ std::error_code &ec);
~mapped_file_region();
- mapmode flags() const;
uint64_t size() const;
char *data() const;
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index 8e163dd..682c5a9 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -23,19 +23,12 @@
#ifndef LLVM_SUPPORT_FORMAT_H
#define LLVM_SUPPORT_FORMAT_H
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
-
#include <cassert>
#include <cstdio>
-#ifdef _MSC_VER
-// FIXME: This define is wrong:
-// - _snprintf does not guarantee that trailing null is always added - if
-// there is no space for null, it does not report any error.
-// - According to C++ standard, snprintf should be visible in the 'std'
-// namespace - this define makes this impossible.
-#define snprintf _snprintf
-#endif
+#include <tuple>
namespace llvm {
@@ -81,101 +74,26 @@ public:
/// printed, this synthesizes the string into a temporary buffer provided and
/// returns whether or not it is big enough.
-template <typename T>
-class format_object1 final : public format_object_base {
- T Val;
-public:
- format_object1(const char *fmt, const T &val)
- : format_object_base(fmt), Val(val) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val);
- }
-};
-
-template <typename T1, typename T2>
-class format_object2 final : public format_object_base {
- T1 Val1;
- T2 Val2;
-public:
- format_object2(const char *fmt, const T1 &val1, const T2 &val2)
- : format_object_base(fmt), Val1(val1), Val2(val2) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2);
- }
-};
-
-template <typename T1, typename T2, typename T3>
-class format_object3 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
-public:
- format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3);
- }
-};
-
-template <typename T1, typename T2, typename T3, typename T4>
-class format_object4 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
-public:
- format_object4(const char *fmt, const T1 &val1, const T2 &val2,
- const T3 &val3, const T4 &val4)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4);
- }
-};
+template <typename... Ts>
+class format_object final : public format_object_base {
+ std::tuple<Ts...> Vals;
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-class format_object5 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
- T5 Val5;
-public:
- format_object5(const char *fmt, const T1 &val1, const T2 &val2,
- const T3 &val3, const T4 &val4, const T5 &val5)
- : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4),
- Val5(val5) {
- }
-
- int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5);
+ template <std::size_t... Is>
+ int snprint_tuple(char *Buffer, unsigned BufferSize,
+ index_sequence<Is...>) const {
+#ifdef _MSC_VER
+ return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#else
+ return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#endif
}
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-class format_object6 final : public format_object_base {
- T1 Val1;
- T2 Val2;
- T3 Val3;
- T4 Val4;
- T5 Val5;
- T6 Val6;
public:
- format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2,
- const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6)
- : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4),
- Val5(Val5), Val6(Val6) { }
+ format_object(const char *fmt, const Ts &... vals)
+ : format_object_base(fmt), Vals(vals...) {}
int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6);
+ return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>());
}
};
@@ -188,44 +106,9 @@ public:
/// OS << format("%0.4f", myfloat) << '\n';
/// \endcode
-template <typename T>
-inline format_object1<T> format(const char *Fmt, const T &Val) {
- return format_object1<T>(Fmt, Val);
-}
-
-template <typename T1, typename T2>
-inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2) {
- return format_object2<T1, T2>(Fmt, Val1, Val2);
-}
-
-template <typename T1, typename T2, typename T3>
- inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2, const T3 &Val3) {
- return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3);
-}
-
-template <typename T1, typename T2, typename T3, typename T4>
-inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1,
- const T2 &Val2, const T3 &Val3,
- const T4 &Val4) {
- return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4);
-}
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1,
- const T2 &Val2, const T3 &Val3,
- const T4 &Val4, const T5 &Val5) {
- return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5);
-}
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-inline format_object6<T1, T2, T3, T4, T5, T6>
-format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3,
- const T4 &Val4, const T5 &Val5, const T6 &Val6) {
- return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4,
- Val5, Val6);
+template <typename... Ts>
+inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) {
+ return format_object<Ts...>(Fmt, Vals...);
}
/// This is a helper class used for left_justify() and right_justify().
@@ -260,21 +143,38 @@ class FormattedNumber {
unsigned Width;
bool Hex;
bool Upper;
+ bool HexPrefix;
friend class raw_ostream;
public:
- FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U)
- : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { }
+ FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U,
+ bool Prefix)
+ : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U),
+ HexPrefix(Prefix) {}
};
/// format_hex - Output \p N as a fixed width hexadecimal. If number will not
/// fit in width, full number is still printed. Examples:
-/// OS << format_hex(255, 4) => 0xff
-/// OS << format_hex(255, 4, true) => 0xFF
-/// OS << format_hex(255, 6) => 0x00ff
-/// OS << format_hex(255, 2) => 0xff
-inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) {
+/// OS << format_hex(255, 4) => 0xff
+/// OS << format_hex(255, 4, true) => 0xFF
+/// OS << format_hex(255, 6) => 0x00ff
+/// OS << format_hex(255, 2) => 0xff
+inline FormattedNumber format_hex(uint64_t N, unsigned Width,
+ bool Upper = false) {
+ assert(Width <= 18 && "hex width must be <= 18");
+ return FormattedNumber(N, 0, Width, true, Upper, true);
+}
+
+/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not
+/// prepend '0x' to the outputted string. If number will not fit in width,
+/// full number is still printed. Examples:
+/// OS << format_hex_no_prefix(255, 4) => ff
+/// OS << format_hex_no_prefix(255, 4, true) => FF
+/// OS << format_hex_no_prefix(255, 6) => 00ff
+/// OS << format_hex_no_prefix(255, 2) => ff
+inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
+ bool Upper = false) {
assert(Width <= 18 && "hex width must be <= 18");
- return FormattedNumber(N, 0, Width, true, Upper);
+ return FormattedNumber(N, 0, Width, true, Upper, false);
}
/// format_decimal - Output \p N as a right justified, fixed-width decimal. If
@@ -284,7 +184,7 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
/// OS << format_decimal(-1, 3) => " -1"
/// OS << format_decimal(12345, 3) => "12345"
inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
- return FormattedNumber(0, N, Width, false, false);
+ return FormattedNumber(0, N, Width, false, false, false);
}
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
index e378602..c2e34bd 100644
--- a/include/llvm/Support/GCOV.h
+++ b/include/llvm/Support/GCOV.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -29,10 +30,7 @@ class GCOVBlock;
class FileInfo;
namespace GCOV {
- enum GCOVVersion {
- V402,
- V404
- };
+enum GCOVVersion { V402, V404 };
} // end GCOV namespace
/// GCOVOptions - A struct for passing gcov options between functions.
@@ -56,7 +54,7 @@ struct GCOVOptions {
class GCOVBuffer {
public:
GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
-
+
/// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
bool readGCNOFormat() {
StringRef File = Buffer->getBuffer().slice(0, 4);
@@ -81,7 +79,7 @@ public:
/// readGCOVVersion - Read GCOV version.
bool readGCOVVersion(GCOV::GCOVVersion &Version) {
- StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
+ StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
if (VersionStr == "*204") {
Cursor += 4;
Version = GCOV::V402;
@@ -99,10 +97,9 @@ public:
/// readFunctionTag - If cursor points to a function tag then increment the
/// cursor and return true otherwise return false.
bool readFunctionTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\1') {
return false;
}
Cursor += 4;
@@ -112,10 +109,9 @@ public:
/// readBlockTag - If cursor points to a block tag then increment the
/// cursor and return true otherwise return false.
bool readBlockTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x41' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -125,10 +121,9 @@ public:
/// readEdgeTag - If cursor points to an edge tag then increment the
/// cursor and return true otherwise return false.
bool readEdgeTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x43' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -138,10 +133,9 @@ public:
/// readLineTag - If cursor points to a line tag then increment the
/// cursor and return true otherwise return false.
bool readLineTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\x45' || Tag[3] != '\x01') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
+ Tag[3] != '\x01') {
return false;
}
Cursor += 4;
@@ -151,10 +145,9 @@ public:
/// readArcTag - If cursor points to an gcda arc tag then increment the
/// cursor and return true otherwise return false.
bool readArcTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\xa1' || Tag[3] != '\1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
+ Tag[3] != '\1') {
return false;
}
Cursor += 4;
@@ -164,10 +157,9 @@ public:
/// readObjectTag - If cursor points to an object summary tag then increment
/// the cursor and return true otherwise return false.
bool readObjectTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\xa1') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\xa1') {
return false;
}
Cursor += 4;
@@ -177,10 +169,9 @@ public:
/// readProgramTag - If cursor points to a program summary tag then increment
/// the cursor and return true otherwise return false.
bool readProgramTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
- if (Tag.empty() ||
- Tag[0] != '\0' || Tag[1] != '\0' ||
- Tag[2] != '\0' || Tag[3] != '\xa3') {
+ StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
+ Tag[3] != '\xa3') {
return false;
}
Cursor += 4;
@@ -188,11 +179,11 @@ public:
}
bool readInt(uint32_t &Val) {
- if (Buffer->getBuffer().size() < Cursor+4) {
- errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
+ if (Buffer->getBuffer().size() < Cursor + 4) {
+ errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
return false;
}
- StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
+ StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
Cursor += 4;
Val = *(const uint32_t *)(Str.data());
return true;
@@ -200,7 +191,8 @@ public:
bool readInt64(uint64_t &Val) {
uint32_t Lo, Hi;
- if (!readInt(Lo) || !readInt(Hi)) return false;
+ if (!readInt(Lo) || !readInt(Hi))
+ return false;
Val = ((uint64_t)Hi << 32) | Lo;
return true;
}
@@ -210,19 +202,21 @@ public:
// Keep reading until we find a non-zero length. This emulates gcov's
// behaviour, which appears to do the same.
while (Len == 0)
- if (!readInt(Len)) return false;
+ if (!readInt(Len))
+ return false;
Len *= 4;
- if (Buffer->getBuffer().size() < Cursor+Len) {
- errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
+ if (Buffer->getBuffer().size() < Cursor + Len) {
+ errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
return false;
}
- Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
+ Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
Cursor += Len;
return true;
}
uint64_t getCursor() const { return Cursor; }
- void advanceCursor(uint32_t n) { Cursor += n*4; }
+ void advanceCursor(uint32_t n) { Cursor += n * 4; }
+
private:
MemoryBuffer *Buffer;
uint64_t Cursor;
@@ -232,13 +226,15 @@ private:
/// (.gcno and .gcda).
class GCOVFile {
public:
- GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
- ProgramCount(0) {}
+ GCOVFile()
+ : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
+ ProgramCount(0) {}
bool readGCNO(GCOVBuffer &Buffer);
bool readGCDA(GCOVBuffer &Buffer);
uint32_t getChecksum() const { return Checksum; }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
bool GCNOInitialized;
GCOV::GCOVVersion Version;
@@ -260,8 +256,8 @@ struct GCOVEdge {
/// GCOVFunction - Collects function information.
class GCOVFunction {
public:
- typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator
- BlockIterator;
+ typedef pointee_iterator<SmallVectorImpl<
+ std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
@@ -274,9 +270,13 @@ public:
BlockIterator block_begin() const { return Blocks.begin(); }
BlockIterator block_end() const { return Blocks.end(); }
+ iterator_range<BlockIterator> blocks() const {
+ return make_range(block_begin(), block_end());
+ }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
GCOVFile &Parent;
uint32_t Ident;
@@ -291,7 +291,7 @@ private:
/// GCOVBlock - Collects block information.
class GCOVBlock {
struct EdgeWeight {
- EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
+ EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
GCOVBlock *Dst;
uint64_t Count;
@@ -302,11 +302,13 @@ class GCOVBlock {
return E1->Dst.Number < E2->Dst.Number;
}
};
+
public:
typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
- GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
- DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
+ GCOVBlock(GCOVFunction &P, uint32_t N)
+ : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
+ DstEdges(), Lines() {}
~GCOVBlock();
const GCOVFunction &getParent() const { return Parent; }
void addLine(uint32_t N) { Lines.push_back(N); }
@@ -331,11 +333,19 @@ public:
EdgeIterator src_begin() const { return SrcEdges.begin(); }
EdgeIterator src_end() const { return SrcEdges.end(); }
+ iterator_range<EdgeIterator> srcs() const {
+ return make_range(src_begin(), src_end());
+ }
+
EdgeIterator dst_begin() const { return DstEdges.begin(); }
EdgeIterator dst_end() const { return DstEdges.end(); }
+ iterator_range<EdgeIterator> dsts() const {
+ return make_range(dst_begin(), dst_end());
+ }
void dump() const;
void collectLineCounts(FileInfo &FI);
+
private:
GCOVFunction &Parent;
uint32_t Number;
@@ -347,8 +357,10 @@ private:
};
class FileInfo {
- // It is unlikely--but possible--for multiple functions to be on the same line.
- // Therefore this typedef allows LineData.Functions to store multiple functions
+ // It is unlikely--but possible--for multiple functions to be on the same
+ // line.
+ // Therefore this typedef allows LineData.Functions to store multiple
+ // functions
// per instance. This is rare, however, so optimize for the common case.
typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
@@ -363,9 +375,9 @@ class FileInfo {
};
struct GCOVCoverage {
- GCOVCoverage(StringRef Name) :
- Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
- BranchesTaken(0) {}
+ GCOVCoverage(StringRef Name)
+ : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
+ BranchesExec(0), BranchesTaken(0) {}
StringRef Name;
@@ -376,30 +388,31 @@ class FileInfo {
uint32_t BranchesExec;
uint32_t BranchesTaken;
};
+
public:
- FileInfo(const GCOVOptions &Options) :
- Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
+ FileInfo(const GCOVOptions &Options)
+ : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
- LineInfo[Filename].Blocks[Line-1].push_back(Block);
+ LineInfo[Filename].Blocks[Line - 1].push_back(Block);
}
void addFunctionLine(StringRef Filename, uint32_t Line,
const GCOVFunction *Function) {
if (Line > LineInfo[Filename].LastLine)
LineInfo[Filename].LastLine = Line;
- LineInfo[Filename].Functions[Line-1].push_back(Function);
+ LineInfo[Filename].Functions[Line - 1].push_back(Function);
}
void setRunCount(uint32_t Runs) { RunCount = Runs; }
void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
- void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile);
+ void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
+ StringRef GCDAFile);
private:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
- void printFunctionSummary(raw_ostream &OS,
- const FunctionVector &Funcs) const;
+ void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
uint32_t LineIndex, uint32_t &BlockNo) const;
void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
@@ -407,23 +420,21 @@ private:
void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
uint64_t Count) const;
- void printCoverage(const GCOVCoverage &Coverage) const;
- void printFuncCoverage() const;
- void printFileCoverage() const;
+ void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
+ void printFuncCoverage(raw_ostream &OS) const;
+ void printFileCoverage(raw_ostream &OS) const;
const GCOVOptions &Options;
StringMap<LineData> LineInfo;
uint32_t RunCount;
uint32_t ProgramCount;
- typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
- FileCoverageList;
+ typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
FileCoverageList FileCoverages;
FuncCoverageMap FuncCoverages;
};
-
}
#endif
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index 6bc4b44..0998eb9 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
@@ -29,76 +30,79 @@
namespace llvm {
-//===----------------------------------------------------------------------===//
-/// DominatorBase - Base class that other, more interesting dominator analyses
+/// \brief Base class that other, more interesting dominator analyses
/// inherit from.
-///
-template <class NodeT>
-class DominatorBase {
+template <class NodeT> class DominatorBase {
protected:
- std::vector<NodeT*> Roots;
- const bool IsPostDominators;
- inline explicit DominatorBase(bool isPostDom) :
- Roots(), IsPostDominators(isPostDom) {}
-public:
+ std::vector<NodeT *> Roots;
+ bool IsPostDominators;
+ explicit DominatorBase(bool isPostDom)
+ : Roots(), IsPostDominators(isPostDom) {}
+ DominatorBase(DominatorBase &&Arg)
+ : Roots(std::move(Arg.Roots)),
+ IsPostDominators(std::move(Arg.IsPostDominators)) {
+ Arg.Roots.clear();
+ }
+ DominatorBase &operator=(DominatorBase &&RHS) {
+ Roots = std::move(RHS.Roots);
+ IsPostDominators = std::move(RHS.IsPostDominators);
+ RHS.Roots.clear();
+ return *this;
+ }
+public:
/// getRoots - Return the root blocks of the current CFG. This may include
/// multiple blocks if we are computing post dominators. For forward
/// dominators, this will always be a single block (the entry node).
///
- inline const std::vector<NodeT*> &getRoots() const { return Roots; }
+ const std::vector<NodeT *> &getRoots() const { return Roots; }
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
};
-
-//===----------------------------------------------------------------------===//
-// DomTreeNodeBase - Dominator Tree Node
-template<class NodeT> class DominatorTreeBase;
+template <class NodeT> class DominatorTreeBase;
struct PostDominatorTree;
-template <class NodeT>
-class DomTreeNodeBase {
+/// \brief Base class for the actual dominator tree node.
+template <class NodeT> class DomTreeNodeBase {
NodeT *TheBB;
DomTreeNodeBase<NodeT> *IDom;
std::vector<DomTreeNodeBase<NodeT> *> Children;
mutable int DFSNumIn, DFSNumOut;
- template<class N> friend class DominatorTreeBase;
+ template <class N> friend class DominatorTreeBase;
friend struct PostDominatorTree;
+
public:
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator
- const_iterator;
+ const_iterator;
- iterator begin() { return Children.begin(); }
- iterator end() { return Children.end(); }
+ iterator begin() { return Children.begin(); }
+ iterator end() { return Children.end(); }
const_iterator begin() const { return Children.begin(); }
- const_iterator end() const { return Children.end(); }
+ const_iterator end() const { return Children.end(); }
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
- const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const {
+ const std::vector<DomTreeNodeBase<NodeT> *> &getChildren() const {
return Children;
}
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
- : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { }
+ : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {}
- DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
- Children.push_back(C);
+ std::unique_ptr<DomTreeNodeBase<NodeT>>
+ addChild(std::unique_ptr<DomTreeNodeBase<NodeT>> C) {
+ Children.push_back(C.get());
return C;
}
- size_t getNumChildren() const {
- return Children.size();
- }
+ size_t getNumChildren() const { return Children.size(); }
- void clearAllChildren() {
- Children.clear();
- }
+ void clearAllChildren() { Children.clear(); }
bool compare(const DomTreeNodeBase<NodeT> *Other) const {
if (getNumChildren() != Other->getNumChildren())
@@ -121,8 +125,8 @@ public:
void setIDom(DomTreeNodeBase<NodeT> *NewIDom) {
assert(IDom && "No immediate dominator?");
if (IDom != NewIDom) {
- typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
- std::find(IDom->Children.begin(), IDom->Children.end(), this);
+ typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I =
+ std::find(IDom->Children.begin(), IDom->Children.end(), this);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
@@ -138,18 +142,18 @@ public:
/// not call them.
unsigned getDFSNumIn() const { return DFSNumIn; }
unsigned getDFSNumOut() const { return DFSNumOut; }
+
private:
// Return true if this node is dominated by other. Use this only if DFS info
// is valid.
bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const {
return this->DFSNumIn >= other->DFSNumIn &&
- this->DFSNumOut <= other->DFSNumOut;
+ this->DFSNumOut <= other->DFSNumOut;
}
};
-template<class NodeT>
-inline raw_ostream &operator<<(raw_ostream &o,
- const DomTreeNodeBase<NodeT> *Node) {
+template <class NodeT>
+raw_ostream &operator<<(raw_ostream &o, const DomTreeNodeBase<NodeT> *Node) {
if (Node->getBlock())
Node->getBlock()->printAsOperand(o, false);
else
@@ -160,25 +164,29 @@ inline raw_ostream &operator<<(raw_ostream &o,
return o << "\n";
}
-template<class NodeT>
-inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
- unsigned Lev) {
- o.indent(2*Lev) << "[" << Lev << "] " << N;
+template <class NodeT>
+void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
+ unsigned Lev) {
+ o.indent(2 * Lev) << "[" << Lev << "] " << N;
for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(),
- E = N->end(); I != E; ++I)
- PrintDomTree<NodeT>(*I, o, Lev+1);
+ E = N->end();
+ I != E; ++I)
+ PrintDomTree<NodeT>(*I, o, Lev + 1);
}
-//===----------------------------------------------------------------------===//
-/// DominatorTree - Calculate the immediate dominator tree for a function.
-///
+// The calculate routine is provided in a separate header but referenced here.
+template <class FuncT, class N>
+void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT,
+ FuncT &F);
-template<class FuncT, class N>
-void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
- FuncT& F);
+/// \brief Core dominator tree base class.
+///
+/// This class is a generic template over graph nodes. It is instantiated for
+/// various graphs in the LLVM IR or in the code generator.
+template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
+ DominatorTreeBase(const DominatorTreeBase &) = delete;
+ DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
-template<class NodeT>
-class DominatorTreeBase : public DominatorBase<NodeT> {
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
assert(A != B);
@@ -187,12 +195,25 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
const DomTreeNodeBase<NodeT> *IDom;
while ((IDom = B->getIDom()) != nullptr && IDom != A && IDom != B)
- B = IDom; // Walk up the tree
+ B = IDom; // Walk up the tree
return IDom != nullptr;
}
+ /// \brief Wipe this tree's state without releasing any resources.
+ ///
+ /// This is essentially a post-move helper only. It leaves the object in an
+ /// assignable and destroyable state, but otherwise invalid.
+ void wipe() {
+ DomTreeNodes.clear();
+ IDoms.clear();
+ Vertex.clear();
+ Info.clear();
+ RootNode = nullptr;
+ }
+
protected:
- typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
+ typedef DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>
+ DomTreeNodeMapType;
DomTreeNodeMapType DomTreeNodes;
DomTreeNodeBase<NodeT> *RootNode;
@@ -208,18 +229,15 @@ protected:
InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {}
};
- DenseMap<NodeT*, NodeT*> IDoms;
+ DenseMap<NodeT *, NodeT *> IDoms;
// Vertex - Map the DFS number to the NodeT*
- std::vector<NodeT*> Vertex;
+ std::vector<NodeT *> Vertex;
// Info - Collection of information used during the computation of idoms.
- DenseMap<NodeT*, InfoRec> Info;
+ DenseMap<NodeT *, InfoRec> Info;
void reset() {
- for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
- E = DomTreeNodes.end(); I != E; ++I)
- delete I->second;
DomTreeNodes.clear();
IDoms.clear();
this->Roots.clear();
@@ -229,27 +247,29 @@ protected:
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
- template<class N, class GraphT>
- void Split(DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* NewBB) {
+ template <class N, class GraphT>
+ void Split(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *NewBB) {
assert(std::distance(GraphT::child_begin(NewBB),
GraphT::child_end(NewBB)) == 1 &&
"NewBB should have a single successor!");
- typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
-
- std::vector<typename GraphT::NodeType*> PredBlocks;
- typedef GraphTraits<Inverse<N> > InvTraits;
- for (typename InvTraits::ChildIteratorType PI =
- InvTraits::child_begin(NewBB),
- PE = InvTraits::child_end(NewBB); PI != PE; ++PI)
+ typename GraphT::NodeType *NewBBSucc = *GraphT::child_begin(NewBB);
+
+ std::vector<typename GraphT::NodeType *> PredBlocks;
+ typedef GraphTraits<Inverse<N>> InvTraits;
+ for (typename InvTraits::ChildIteratorType
+ PI = InvTraits::child_begin(NewBB),
+ PE = InvTraits::child_end(NewBB);
+ PI != PE; ++PI)
PredBlocks.push_back(*PI);
assert(!PredBlocks.empty() && "No predblocks?");
bool NewBBDominatesNewBBSucc = true;
- for (typename InvTraits::ChildIteratorType PI =
- InvTraits::child_begin(NewBBSucc),
- E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) {
+ for (typename InvTraits::ChildIteratorType
+ PI = InvTraits::child_begin(NewBBSucc),
+ E = InvTraits::child_end(NewBBSucc);
+ PI != E; ++PI) {
typename InvTraits::NodeType *ND = *PI;
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
DT.isReachableFromEntry(ND)) {
@@ -292,8 +312,31 @@ protected:
public:
explicit DominatorTreeBase(bool isPostDom)
- : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
- virtual ~DominatorTreeBase() { reset(); }
+ : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
+
+ DominatorTreeBase(DominatorTreeBase &&Arg)
+ : DominatorBase<NodeT>(
+ std::move(static_cast<DominatorBase<NodeT> &>(Arg))),
+ DomTreeNodes(std::move(Arg.DomTreeNodes)),
+ RootNode(std::move(Arg.RootNode)),
+ DFSInfoValid(std::move(Arg.DFSInfoValid)),
+ SlowQueries(std::move(Arg.SlowQueries)), IDoms(std::move(Arg.IDoms)),
+ Vertex(std::move(Arg.Vertex)), Info(std::move(Arg.Info)) {
+ Arg.wipe();
+ }
+ DominatorTreeBase &operator=(DominatorTreeBase &&RHS) {
+ DominatorBase<NodeT>::operator=(
+ std::move(static_cast<DominatorBase<NodeT> &>(RHS)));
+ DomTreeNodes = std::move(RHS.DomTreeNodes);
+ RootNode = std::move(RHS.RootNode);
+ DFSInfoValid = std::move(RHS.DFSInfoValid);
+ SlowQueries = std::move(RHS.SlowQueries);
+ IDoms = std::move(RHS.IDoms);
+ Vertex = std::move(RHS.Vertex);
+ Info = std::move(RHS.Info);
+ RHS.wipe();
+ return *this;
+ }
/// compare - Return false if the other dominator tree base matches this
/// dominator tree base. Otherwise return true.
@@ -304,35 +347,38 @@ public:
return true;
for (typename DomTreeNodeMapType::const_iterator
- I = this->DomTreeNodes.begin(),
- E = this->DomTreeNodes.end(); I != E; ++I) {
+ I = this->DomTreeNodes.begin(),
+ E = this->DomTreeNodes.end();
+ I != E; ++I) {
NodeT *BB = I->first;
- typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB);
+ typename DomTreeNodeMapType::const_iterator OI =
+ OtherDomTreeNodes.find(BB);
if (OI == OtherDomTreeNodes.end())
return true;
- DomTreeNodeBase<NodeT>* MyNd = I->second;
- DomTreeNodeBase<NodeT>* OtherNd = OI->second;
+ DomTreeNodeBase<NodeT> &MyNd = *I->second;
+ DomTreeNodeBase<NodeT> &OtherNd = *OI->second;
- if (MyNd->compare(OtherNd))
+ if (MyNd.compare(&OtherNd))
return true;
}
return false;
}
- virtual void releaseMemory() { reset(); }
+ void releaseMemory() { reset(); }
/// getNode - return the (Post)DominatorTree node for the specified basic
/// block. This is the same as using operator[] on this class.
///
- inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
- return DomTreeNodes.lookup(BB);
+ DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
+ auto I = DomTreeNodes.find(BB);
+ if (I != DomTreeNodes.end())
+ return I->second.get();
+ return nullptr;
}
- inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const {
- return getNode(BB);
- }
+ DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); }
/// getRootNode - This returns the entry node for the CFG of the function. If
/// this tree represents the post-dominance relations for a function, however,
@@ -376,21 +422,19 @@ public:
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
- bool isReachableFromEntry(const NodeT* A) const {
+ bool isReachableFromEntry(const NodeT *A) const {
assert(!this->isPostDominator() &&
"This is not implemented for post dominators");
return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
}
- inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const {
- return A;
- }
+ bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { return A; }
/// dominates - Returns true iff A dominates B. Note that this is not a
/// constant time operation!
///
- inline bool dominates(const DomTreeNodeBase<NodeT> *A,
- const DomTreeNodeBase<NodeT> *B) const {
+ bool dominates(const DomTreeNodeBase<NodeT> *A,
+ const DomTreeNodeBase<NodeT> *B) const {
// A node trivially dominates itself.
if (B == A)
return true;
@@ -473,7 +517,7 @@ public:
}
// Collect NodeA dominators set.
- SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms;
+ SmallPtrSet<DomTreeNodeBase<NodeT> *, 16> NodeADoms;
NodeADoms.insert(NodeA);
DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom();
while (IDomA) {
@@ -512,8 +556,8 @@ public:
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
- return DomTreeNodes[BB] =
- IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
+ return (DomTreeNodes[BB] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
}
/// changeImmediateDominator - This method is used to update the dominator
@@ -538,11 +582,11 @@ public:
assert(Node && "Removing node that isn't in dominator tree.");
assert(Node->getChildren().empty() && "Node is not a leaf node.");
- // Remove node from immediate dominator's children list.
+ // Remove node from immediate dominator's children list.
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
if (IDom) {
- typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
- std::find(IDom->Children.begin(), IDom->Children.end(), Node);
+ typename std::vector<DomTreeNodeBase<NodeT> *>::iterator I =
+ std::find(IDom->Children.begin(), IDom->Children.end(), Node);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
@@ -550,24 +594,16 @@ public:
}
DomTreeNodes.erase(BB);
- delete Node;
- }
-
- /// removeNode - Removes a node from the dominator tree. Block must not
- /// dominate any other blocks. Invalidates any node pointing to removed
- /// block.
- void removeNode(NodeT *BB) {
- assert(getNode(BB) && "Removing node that isn't in dominator tree.");
- DomTreeNodes.erase(BB);
}
/// splitBlock - BB is split and now it has one successor. Update dominator
/// tree to reflect this change.
- void splitBlock(NodeT* NewBB) {
+ void splitBlock(NodeT *NewBB) {
if (this->IsPostDominators)
- this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB);
+ this->Split<Inverse<NodeT *>, GraphTraits<Inverse<NodeT *>>>(*this,
+ NewBB);
else
- this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB);
+ this->Split<NodeT *, GraphTraits<NodeT *>>(*this, NewBB);
}
/// print - Convert to human readable form
@@ -588,28 +624,27 @@ public:
}
protected:
- template<class GraphT>
- friend typename GraphT::NodeType* Eval(
- DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* V,
- unsigned LastLinked);
+ template <class GraphT>
+ friend typename GraphT::NodeType *
+ Eval(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *V, unsigned LastLinked);
- template<class GraphT>
- friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
- typename GraphT::NodeType* V,
- unsigned N);
+ template <class GraphT>
+ friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType> &DT,
+ typename GraphT::NodeType *V, unsigned N);
- template<class FuncT, class N>
- friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
- FuncT& F);
+ template <class FuncT, class N>
+ friend void
+ Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F);
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
/// dominator tree in dfs order.
void updateDFSNumbers() const {
unsigned DFSNum = 0;
- SmallVector<std::pair<const DomTreeNodeBase<NodeT>*,
- typename DomTreeNodeBase<NodeT>::const_iterator>, 32> WorkStack;
+ SmallVector<std::pair<const DomTreeNodeBase<NodeT> *,
+ typename DomTreeNodeBase<NodeT>::const_iterator>,
+ 32> WorkStack;
const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
@@ -626,7 +661,7 @@ protected:
while (!WorkStack.empty()) {
const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
typename DomTreeNodeBase<NodeT>::const_iterator ChildIt =
- WorkStack.back().second;
+ WorkStack.back().second;
// If we visited all of the children of this node, "recurse" back up the
// stack setting the DFOutNum.
@@ -660,23 +695,18 @@ protected:
// Add a new tree node for this NodeT, and link it as a child of
// IDomNode
- DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
- return this->DomTreeNodes[BB] = IDomNode->addChild(C);
+ return (this->DomTreeNodes[BB] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
}
- inline NodeT *getIDom(NodeT *BB) const {
- return IDoms.lookup(BB);
- }
+ NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); }
- inline void addRoot(NodeT* BB) {
- this->Roots.push_back(BB);
- }
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
public:
/// recalculate - compute a dominator tree for the given function
- template<class FT>
- void recalculate(FT& F) {
- typedef GraphTraits<FT*> TraitsTy;
+ template <class FT> void recalculate(FT &F) {
+ typedef GraphTraits<FT *> TraitsTy;
reset();
this->Vertex.push_back(nullptr);
@@ -687,27 +717,29 @@ public:
this->IDoms[entry] = nullptr;
this->DomTreeNodes[entry] = nullptr;
- Calculate<FT, NodeT*>(*this, F);
+ Calculate<FT, NodeT *>(*this, F);
} else {
// Initialize the roots list
for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
- E = TraitsTy::nodes_end(&F); I != E; ++I) {
+ E = TraitsTy::nodes_end(&F);
+ I != E; ++I) {
if (TraitsTy::child_begin(I) == TraitsTy::child_end(I))
addRoot(I);
- // Prepopulate maps so that we don't get iterator invalidation issues later.
+ // Prepopulate maps so that we don't get iterator invalidation issues
+ // later.
this->IDoms[I] = nullptr;
this->DomTreeNodes[I] = nullptr;
}
- Calculate<FT, Inverse<NodeT*> >(*this, F);
+ Calculate<FT, Inverse<NodeT *>>(*this, F);
}
}
};
// These two functions are declared out of line as a workaround for building
// with old (< r147295) versions of clang because of pr11642.
-template<class NodeT>
+template <class NodeT>
bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const {
if (A == B)
return true;
@@ -718,9 +750,9 @@ bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const {
return dominates(getNode(const_cast<NodeT *>(A)),
getNode(const_cast<NodeT *>(B)));
}
-template<class NodeT>
-bool
-DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) const {
+template <class NodeT>
+bool DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A,
+ const NodeT *B) const {
if (A == B)
return false;
diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h
index ad4f8a9..7c065f9 100644
--- a/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/include/llvm/Support/GenericDomTreeConstruction.h
@@ -251,15 +251,18 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
// an infinite loop.
typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr;
- DT.DomTreeNodes[Root] = DT.RootNode =
- new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr);
+ DT.RootNode =
+ (DT.DomTreeNodes[Root] =
+ llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>(
+ Root, nullptr)).get();
// Loop over all of the reachable blocks in the function...
for (unsigned i = 2; i <= N; ++i) {
typename GraphT::NodeType* W = DT.Vertex[i];
- DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W];
- if (BBNode) continue; // Haven't calculated this node yet?
+ // Don't replace this with 'count', the insertion side effect is important
+ if (DT.DomTreeNodes[W])
+ continue; // Haven't calculated this node yet?
typename GraphT::NodeType* ImmDom = DT.getIDom(W);
@@ -271,15 +274,16 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode
- DomTreeNodeBase<typename GraphT::NodeType> *C =
- new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode);
- DT.DomTreeNodes[W] = IDomNode->addChild(C);
+ DT.DomTreeNodes[W] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>(
+ W, IDomNode));
}
// Free temporary memory used to construct idom's
DT.IDoms.clear();
DT.Info.clear();
- std::vector<typename GraphT::NodeType*>().swap(DT.Vertex);
+ DT.Vertex.clear();
+ DT.Vertex.shrink_to_fit();
DT.updateDFSNumbers();
}
diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h
index 61c65da..8e88d42 100644
--- a/include/llvm/Support/LockFileManager.h
+++ b/include/llvm/Support/LockFileManager.h
@@ -57,8 +57,8 @@ private:
Optional<std::pair<std::string, int> > Owner;
Optional<std::error_code> Error;
- LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION;
- LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION;
+ LockFileManager(const LockFileManager &) = delete;
+ LockFileManager &operator=(const LockFileManager &) = delete;
static Optional<std::pair<std::string, int> >
readLockFile(StringRef LockFileName);
@@ -77,6 +77,10 @@ public:
/// \brief For a shared lock, wait until the owner releases the lock.
WaitForUnlockResult waitForUnlock();
+
+ /// \brief Remove the lock file. This may delete a different lock file than
+ /// the one previously read if there is a race.
+ std::error_code unsafeRemoveLockFile();
};
} // end namespace llvm
diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h
index c07bd88..7751275 100644
--- a/include/llvm/Support/MachO.h
+++ b/include/llvm/Support/MachO.h
@@ -130,8 +130,8 @@ namespace llvm {
LC_DATA_IN_CODE = 0x00000029u,
LC_SOURCE_VERSION = 0x0000002Au,
LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu,
- // 0x0000002Cu,
- LC_LINKER_OPTIONS = 0x0000002Du,
+ LC_ENCRYPTION_INFO_64 = 0x0000002Cu,
+ LC_LINKER_OPTION = 0x0000002Du,
LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu
};
@@ -842,6 +842,15 @@ namespace llvm {
uint32_t cryptid;
};
+ struct encryption_info_command_64 {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t cryptoff;
+ uint32_t cryptsize;
+ uint32_t cryptid;
+ uint32_t pad;
+ };
+
struct version_min_command {
uint32_t cmd; // LC_VERSION_MIN_MACOSX or
// LC_VERSION_MIN_IPHONEOS
@@ -865,7 +874,7 @@ namespace llvm {
uint32_t export_size;
};
- struct linker_options_command {
+ struct linker_option_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t count;
@@ -1098,6 +1107,61 @@ namespace llvm {
sys::swapByteOrder(d.dylib.compatibility_version);
}
+ inline void swapStruct(sub_framework_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.umbrella);
+ }
+
+ inline void swapStruct(sub_umbrella_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.sub_umbrella);
+ }
+
+ inline void swapStruct(sub_library_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.sub_library);
+ }
+
+ inline void swapStruct(sub_client_command &s) {
+ sys::swapByteOrder(s.cmd);
+ sys::swapByteOrder(s.cmdsize);
+ sys::swapByteOrder(s.client);
+ }
+
+ inline void swapStruct(routines_command &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.init_address);
+ sys::swapByteOrder(r.init_module);
+ sys::swapByteOrder(r.reserved1);
+ sys::swapByteOrder(r.reserved2);
+ sys::swapByteOrder(r.reserved3);
+ sys::swapByteOrder(r.reserved4);
+ sys::swapByteOrder(r.reserved5);
+ sys::swapByteOrder(r.reserved6);
+ }
+
+ inline void swapStruct(routines_command_64 &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.init_address);
+ sys::swapByteOrder(r.init_module);
+ sys::swapByteOrder(r.reserved1);
+ sys::swapByteOrder(r.reserved2);
+ sys::swapByteOrder(r.reserved3);
+ sys::swapByteOrder(r.reserved4);
+ sys::swapByteOrder(r.reserved5);
+ sys::swapByteOrder(r.reserved6);
+ }
+
+ inline void swapStruct(thread_command &t) {
+ sys::swapByteOrder(t.cmd);
+ sys::swapByteOrder(t.cmdsize);
+ }
+
inline void swapStruct(dylinker_command &d) {
sys::swapByteOrder(d.cmd);
sys::swapByteOrder(d.cmdsize);
@@ -1109,6 +1173,12 @@ namespace llvm {
sys::swapByteOrder(u.cmdsize);
}
+ inline void swapStruct(rpath_command &r) {
+ sys::swapByteOrder(r.cmd);
+ sys::swapByteOrder(r.cmdsize);
+ sys::swapByteOrder(r.path);
+ }
+
inline void swapStruct(source_version_command &s) {
sys::swapByteOrder(s.cmd);
sys::swapByteOrder(s.cmdsize);
@@ -1122,6 +1192,23 @@ namespace llvm {
sys::swapByteOrder(e.stacksize);
}
+ inline void swapStruct(encryption_info_command &e) {
+ sys::swapByteOrder(e.cmd);
+ sys::swapByteOrder(e.cmdsize);
+ sys::swapByteOrder(e.cryptoff);
+ sys::swapByteOrder(e.cryptsize);
+ sys::swapByteOrder(e.cryptid);
+ }
+
+ inline void swapStruct(encryption_info_command_64 &e) {
+ sys::swapByteOrder(e.cmd);
+ sys::swapByteOrder(e.cmdsize);
+ sys::swapByteOrder(e.cryptoff);
+ sys::swapByteOrder(e.cryptsize);
+ sys::swapByteOrder(e.cryptid);
+ sys::swapByteOrder(e.pad);
+ }
+
inline void swapStruct(dysymtab_command &dst) {
sys::swapByteOrder(dst.cmd);
sys::swapByteOrder(dst.cmdsize);
@@ -1174,7 +1261,7 @@ namespace llvm {
sys::swapByteOrder(C.datasize);
}
- inline void swapStruct(linker_options_command &C) {
+ inline void swapStruct(linker_option_command &C) {
sys::swapByteOrder(C.cmd);
sys::swapByteOrder(C.cmdsize);
sys::swapByteOrder(C.count);
@@ -1331,6 +1418,262 @@ namespace llvm {
CPU_SUBTYPE_MC980000_ALL = CPU_SUBTYPE_POWERPC_ALL,
CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601
};
+
+ struct x86_thread_state64_t {
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rdi;
+ uint64_t rsi;
+ uint64_t rbp;
+ uint64_t rsp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+ uint64_t rflags;
+ uint64_t cs;
+ uint64_t fs;
+ uint64_t gs;
+ };
+
+ enum x86_fp_control_precis {
+ x86_FP_PREC_24B = 0,
+ x86_FP_PREC_53B = 2,
+ x86_FP_PREC_64B = 3
+ };
+
+ enum x86_fp_control_rc {
+ x86_FP_RND_NEAR = 0,
+ x86_FP_RND_DOWN = 1,
+ x86_FP_RND_UP = 2,
+ x86_FP_CHOP = 3
+ };
+
+ struct fp_control_t {
+ unsigned short
+ invalid :1,
+ denorm :1,
+ zdiv :1,
+ ovrfl :1,
+ undfl :1,
+ precis :1,
+ :2,
+ pc :2,
+ rc :2,
+ :1,
+ :3;
+ };
+
+ struct fp_status_t {
+ unsigned short
+ invalid :1,
+ denorm :1,
+ zdiv :1,
+ ovrfl :1,
+ undfl :1,
+ precis :1,
+ stkflt :1,
+ errsumm :1,
+ c0 :1,
+ c1 :1,
+ c2 :1,
+ tos :3,
+ c3 :1,
+ busy :1;
+ };
+
+ struct mmst_reg_t {
+ char mmst_reg[10];
+ char mmst_rsrv[6];
+ };
+
+ struct xmm_reg_t {
+ char xmm_reg[16];
+ };
+
+ struct x86_float_state64_t {
+ int32_t fpu_reserved[2];
+ fp_control_t fpu_fcw;
+ fp_status_t fpu_fsw;
+ uint8_t fpu_ftw;
+ uint8_t fpu_rsrv1;
+ uint16_t fpu_fop;
+ uint32_t fpu_ip;
+ uint16_t fpu_cs;
+ uint16_t fpu_rsrv2;
+ uint32_t fpu_dp;
+ uint16_t fpu_ds;
+ uint16_t fpu_rsrv3;
+ uint32_t fpu_mxcsr;
+ uint32_t fpu_mxcsrmask;
+ mmst_reg_t fpu_stmm0;
+ mmst_reg_t fpu_stmm1;
+ mmst_reg_t fpu_stmm2;
+ mmst_reg_t fpu_stmm3;
+ mmst_reg_t fpu_stmm4;
+ mmst_reg_t fpu_stmm5;
+ mmst_reg_t fpu_stmm6;
+ mmst_reg_t fpu_stmm7;
+ xmm_reg_t fpu_xmm0;
+ xmm_reg_t fpu_xmm1;
+ xmm_reg_t fpu_xmm2;
+ xmm_reg_t fpu_xmm3;
+ xmm_reg_t fpu_xmm4;
+ xmm_reg_t fpu_xmm5;
+ xmm_reg_t fpu_xmm6;
+ xmm_reg_t fpu_xmm7;
+ xmm_reg_t fpu_xmm8;
+ xmm_reg_t fpu_xmm9;
+ xmm_reg_t fpu_xmm10;
+ xmm_reg_t fpu_xmm11;
+ xmm_reg_t fpu_xmm12;
+ xmm_reg_t fpu_xmm13;
+ xmm_reg_t fpu_xmm14;
+ xmm_reg_t fpu_xmm15;
+ char fpu_rsrv4[6*16];
+ uint32_t fpu_reserved1;
+ };
+
+ struct x86_exception_state64_t {
+ uint16_t trapno;
+ uint16_t cpu;
+ uint32_t err;
+ uint64_t faultvaddr;
+ };
+
+ inline void swapStruct(x86_thread_state64_t &x) {
+ sys::swapByteOrder(x.rax);
+ sys::swapByteOrder(x.rbx);
+ sys::swapByteOrder(x.rcx);
+ sys::swapByteOrder(x.rdx);
+ sys::swapByteOrder(x.rdi);
+ sys::swapByteOrder(x.rsi);
+ sys::swapByteOrder(x.rbp);
+ sys::swapByteOrder(x.rsp);
+ sys::swapByteOrder(x.r8);
+ sys::swapByteOrder(x.r9);
+ sys::swapByteOrder(x.r10);
+ sys::swapByteOrder(x.r11);
+ sys::swapByteOrder(x.r12);
+ sys::swapByteOrder(x.r13);
+ sys::swapByteOrder(x.r14);
+ sys::swapByteOrder(x.r15);
+ sys::swapByteOrder(x.rip);
+ sys::swapByteOrder(x.rflags);
+ sys::swapByteOrder(x.cs);
+ sys::swapByteOrder(x.fs);
+ sys::swapByteOrder(x.gs);
+ }
+
+ inline void swapStruct(x86_float_state64_t &x) {
+ sys::swapByteOrder(x.fpu_reserved[0]);
+ sys::swapByteOrder(x.fpu_reserved[1]);
+ // TODO swap: fp_control_t fpu_fcw;
+ // TODO swap: fp_status_t fpu_fsw;
+ sys::swapByteOrder(x.fpu_fop);
+ sys::swapByteOrder(x.fpu_ip);
+ sys::swapByteOrder(x.fpu_cs);
+ sys::swapByteOrder(x.fpu_rsrv2);
+ sys::swapByteOrder(x.fpu_dp);
+ sys::swapByteOrder(x.fpu_ds);
+ sys::swapByteOrder(x.fpu_rsrv3);
+ sys::swapByteOrder(x.fpu_mxcsr);
+ sys::swapByteOrder(x.fpu_mxcsrmask);
+ sys::swapByteOrder(x.fpu_reserved1);
+ }
+
+ inline void swapStruct(x86_exception_state64_t &x) {
+ sys::swapByteOrder(x.trapno);
+ sys::swapByteOrder(x.cpu);
+ sys::swapByteOrder(x.err);
+ sys::swapByteOrder(x.faultvaddr);
+ }
+
+ struct x86_state_hdr_t {
+ uint32_t flavor;
+ uint32_t count;
+ };
+
+ struct x86_thread_state_t {
+ x86_state_hdr_t tsh;
+ union {
+ x86_thread_state64_t ts64;
+ } uts;
+ };
+
+ struct x86_float_state_t {
+ x86_state_hdr_t fsh;
+ union {
+ x86_float_state64_t fs64;
+ } ufs;
+ };
+
+ struct x86_exception_state_t {
+ x86_state_hdr_t esh;
+ union {
+ x86_exception_state64_t es64;
+ } ues;
+ };
+
+ inline void swapStruct(x86_state_hdr_t &x) {
+ sys::swapByteOrder(x.flavor);
+ sys::swapByteOrder(x.count);
+ }
+
+ enum X86ThreadFlavors {
+ x86_THREAD_STATE32 = 1,
+ x86_FLOAT_STATE32 = 2,
+ x86_EXCEPTION_STATE32 = 3,
+ x86_THREAD_STATE64 = 4,
+ x86_FLOAT_STATE64 = 5,
+ x86_EXCEPTION_STATE64 = 6,
+ x86_THREAD_STATE = 7,
+ x86_FLOAT_STATE = 8,
+ x86_EXCEPTION_STATE = 9,
+ x86_DEBUG_STATE32 = 10,
+ x86_DEBUG_STATE64 = 11,
+ x86_DEBUG_STATE = 12
+ };
+
+ inline void swapStruct(x86_thread_state_t &x) {
+ swapStruct(x.tsh);
+ if (x.tsh.flavor == x86_THREAD_STATE64)
+ swapStruct(x.uts.ts64);
+ }
+
+ inline void swapStruct(x86_float_state_t &x) {
+ swapStruct(x.fsh);
+ if (x.fsh.flavor == x86_FLOAT_STATE64)
+ swapStruct(x.ufs.fs64);
+ }
+
+ inline void swapStruct(x86_exception_state_t &x) {
+ swapStruct(x.esh);
+ if (x.esh.flavor == x86_EXCEPTION_STATE64)
+ swapStruct(x.ues.es64);
+ }
+
+ const uint32_t x86_THREAD_STATE64_COUNT =
+ sizeof(x86_thread_state64_t) / sizeof(uint32_t);
+ const uint32_t x86_FLOAT_STATE64_COUNT =
+ sizeof(x86_float_state64_t) / sizeof(uint32_t);
+ const uint32_t x86_EXCEPTION_STATE64_COUNT =
+ sizeof(x86_exception_state64_t) / sizeof(uint32_t);
+
+ const uint32_t x86_THREAD_STATE_COUNT =
+ sizeof(x86_thread_state_t) / sizeof(uint32_t);
+ const uint32_t x86_FLOAT_STATE_COUNT =
+ sizeof(x86_float_state_t) / sizeof(uint32_t);
+ const uint32_t x86_EXCEPTION_STATE_COUNT =
+ sizeof(x86_exception_state_t) / sizeof(uint32_t);
+
} // end namespace MachO
} // end namespace llvm
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 9d16182..acffb46 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -35,78 +35,66 @@ enum ZeroBehavior {
ZB_Width
};
-/// \brief Count number of 0's from the least significant bit to the most
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
-/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, std::size_t>::type
-countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
- (void)ZB;
-
- if (!Val)
- return std::numeric_limits<T>::digits;
- if (Val & 0x1)
- return 0;
-
- // Bisection method.
- std::size_t ZeroBits = 0;
- T Shift = std::numeric_limits<T>::digits >> 1;
- T Mask = std::numeric_limits<T>::max() >> Shift;
- while (Shift) {
- if ((Val & Mask) == 0) {
- Val >>= Shift;
- ZeroBits |= Shift;
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
+ static std::size_t count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+ if (Val & 0x1)
+ return 0;
+
+ // Bisection method.
+ std::size_t ZeroBits = 0;
+ T Shift = std::numeric_limits<T>::digits >> 1;
+ T Mask = std::numeric_limits<T>::max() >> Shift;
+ while (Shift) {
+ if ((Val & Mask) == 0) {
+ Val >>= Shift;
+ ZeroBits |= Shift;
+ }
+ Shift >>= 1;
+ Mask >>= Shift;
}
- Shift >>= 1;
- Mask >>= Shift;
+ return ZeroBits;
}
- return ZeroBits;
-}
-
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, std::size_t>::type
-countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION;
+};
#if __GNUC__ >= 4 || _MSC_VER
-template <>
-inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 32;
+template <typename T> struct TrailingZerosCounter<T, 4> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_ctz(Val);
+ return __builtin_ctz(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanForward(&Index, Val);
- return Index;
+ unsigned long Index;
+ _BitScanForward(&Index, Val);
+ return Index;
#endif
-}
+ }
+};
#if !defined(_MSC_VER) || defined(_M_X64)
-template <>
-inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 64;
+template <typename T> struct TrailingZerosCounter<T, 8> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_ctzll(Val);
+ return __builtin_ctzll(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanForward64(&Index, Val);
- return Index;
+ unsigned long Index;
+ _BitScanForward64(&Index, Val);
+ return Index;
#endif
-}
+ }
+};
#endif
#endif
+} // namespace detail
-/// \brief Count number of 0's from the most significant bit to the least
+/// \brief Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
@@ -114,63 +102,81 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, std::size_t>::type
-countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
- (void)ZB;
-
- if (!Val)
- return std::numeric_limits<T>::digits;
-
- // Bisection method.
- std::size_t ZeroBits = 0;
- for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
- T Tmp = Val >> Shift;
- if (Tmp)
- Val = Tmp;
- else
- ZeroBits |= Shift;
+std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
+ static std::size_t count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+
+ // Bisection method.
+ std::size_t ZeroBits = 0;
+ for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
+ T Tmp = Val >> Shift;
+ if (Tmp)
+ Val = Tmp;
+ else
+ ZeroBits |= Shift;
+ }
+ return ZeroBits;
}
- return ZeroBits;
-}
-
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, std::size_t>::type
-countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION;
+};
#if __GNUC__ >= 4 || _MSC_VER
-template <>
-inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 32;
+template <typename T> struct LeadingZerosCounter<T, 4> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_clz(Val);
+ return __builtin_clz(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanReverse(&Index, Val);
- return Index ^ 31;
+ unsigned long Index;
+ _BitScanReverse(&Index, Val);
+ return Index ^ 31;
#endif
-}
+ }
+};
#if !defined(_MSC_VER) || defined(_M_X64)
-template <>
-inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
- if (ZB != ZB_Undefined && Val == 0)
- return 64;
+template <typename T> struct LeadingZerosCounter<T, 8> {
+ static std::size_t count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
- return __builtin_clzll(Val);
+ return __builtin_clzll(Val);
#elif _MSC_VER
- unsigned long Index;
- _BitScanReverse64(&Index, Val);
- return Index ^ 63;
+ unsigned long Index;
+ _BitScanReverse64(&Index, Val);
+ return Index ^ 63;
#endif
-}
+ }
+};
#endif
#endif
+} // namespace detail
+
+/// \brief Count number of 0's from the most significant bit to the least
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+/// valid arguments.
+template <typename T>
+std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
/// \brief Get the index of the first set bit starting from the least
/// significant bit.
@@ -179,22 +185,13 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, T>::type
-findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
+template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
return countTrailingZeros(Val, ZB_Undefined);
}
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, T>::type
-findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION;
-
/// \brief Get the index of the last set bit starting from the least
/// significant bit.
///
@@ -202,10 +199,7 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION;
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- !std::numeric_limits<T>::is_signed, T>::type
-findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
+template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
@@ -215,12 +209,6 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
(std::numeric_limits<T>::digits - 1);
}
-// Disable signed.
-template <typename T>
-typename std::enable_if<std::numeric_limits<T>::is_integer &&
- std::numeric_limits<T>::is_signed, T>::type
-findLastSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION;
-
/// \brief Macro compressed bit reversal table for 256 bits.
///
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
@@ -387,62 +375,78 @@ inline uint64_t ByteSwap_64(uint64_t Value) {
return sys::SwapByteOrder_64(Value);
}
-/// CountLeadingOnes_32 - this function performs the operation of
-/// counting the number of ones from the most significant bit to the first zero
-/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8.
-/// Returns 32 if the word is all ones.
-inline unsigned CountLeadingOnes_32(uint32_t Value) {
- return countLeadingZeros(~Value);
-}
-
-/// CountLeadingOnes_64 - This function performs the operation
-/// of counting the number of ones from the most significant bit to the first
-/// zero bit (64 bit edition.)
-/// Returns 64 if the word is all ones.
-inline unsigned CountLeadingOnes_64(uint64_t Value) {
- return countLeadingZeros(~Value);
-}
-
-/// CountTrailingOnes_32 - this function performs the operation of
-/// counting the number of ones from the least significant bit to the first zero
-/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8.
-/// Returns 32 if the word is all ones.
-inline unsigned CountTrailingOnes_32(uint32_t Value) {
- return countTrailingZeros(~Value);
-}
-
-/// CountTrailingOnes_64 - This function performs the operation
-/// of counting the number of ones from the least significant bit to the first
-/// zero bit (64 bit edition.)
-/// Returns 64 if the word is all ones.
-inline unsigned CountTrailingOnes_64(uint64_t Value) {
- return countTrailingZeros(~Value);
+/// \brief Count the number of ones from the most significant bit to the first
+/// zero bit.
+///
+/// Ex. CountLeadingOnes(0xFF0FFF00) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return countLeadingZeros(~Value, ZB);
}
-/// CountPopulation_32 - this function counts the number of set bits in a value.
-/// Ex. CountPopulation(0xF000F000) = 8
-/// Returns 0 if the word is zero.
-inline unsigned CountPopulation_32(uint32_t Value) {
+/// \brief Count the number of ones from the least significant bit to the first
+/// zero bit.
+///
+/// Ex. countTrailingOnes(0x00FF00FF) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return countTrailingZeros(~Value, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct PopulationCounter {
+ static unsigned count(T Value) {
+ // Generic version, forward to 32 bits.
+ static_assert(SizeOfT <= 4, "Not implemented!");
#if __GNUC__ >= 4
- return __builtin_popcount(Value);
+ return __builtin_popcount(Value);
#else
- uint32_t v = Value - ((Value >> 1) & 0x55555555);
- v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
- return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
+ uint32_t v = Value;
+ v = v - ((v >> 1) & 0x55555555);
+ v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+ return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
#endif
-}
+ }
+};
-/// CountPopulation_64 - this function counts the number of set bits in a value,
-/// (64 bit edition.)
-inline unsigned CountPopulation_64(uint64_t Value) {
+template <typename T> struct PopulationCounter<T, 8> {
+ static unsigned count(T Value) {
#if __GNUC__ >= 4
- return __builtin_popcountll(Value);
+ return __builtin_popcountll(Value);
#else
- uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL);
- v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
- v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
- return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
+ uint64_t v = Value;
+ v = v - ((v >> 1) & 0x5555555555555555ULL);
+ v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+ v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+ return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
#endif
+ }
+};
+} // namespace detail
+
+/// \brief Count the number of set bits in a value.
+/// Ex. countPopulation(0xF000F000) = 8
+/// Returns 0 if the word is zero.
+template <typename T>
+inline unsigned countPopulation(T Value) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
/// Log2_32 - This function returns the floor log base 2 of the specified value,
diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index e2f8d7e..cc65ca5 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -40,8 +40,8 @@ class MemoryBuffer {
const char *BufferStart; // Start of the buffer.
const char *BufferEnd; // End of the buffer.
- MemoryBuffer(const MemoryBuffer &) LLVM_DELETED_FUNCTION;
- MemoryBuffer &operator=(const MemoryBuffer &) LLVM_DELETED_FUNCTION;
+ MemoryBuffer(const MemoryBuffer &) = delete;
+ MemoryBuffer &operator=(const MemoryBuffer &) = delete;
protected:
MemoryBuffer() {}
void init(const char *BufStart, const char *BufEnd,
diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h
index 97dd501..ae69634 100644
--- a/include/llvm/Support/Mutex.h
+++ b/include/llvm/Support/Mutex.h
@@ -76,8 +76,8 @@ namespace llvm
/// @name Do Not Implement
/// @{
private:
- MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION;
- void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION;
+ MutexImpl(const MutexImpl &) = delete;
+ void operator=(const MutexImpl &) = delete;
/// @}
};
diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h
index b9f941d..07b64b6 100644
--- a/include/llvm/Support/MutexGuard.h
+++ b/include/llvm/Support/MutexGuard.h
@@ -26,8 +26,8 @@ namespace llvm {
/// @brief Guard a section of code with a Mutex.
class MutexGuard {
sys::Mutex &M;
- MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION;
- void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION;
+ MutexGuard(const MutexGuard &) = delete;
+ void operator=(const MutexGuard &) = delete;
public:
MutexGuard(sys::Mutex &m) : M(m) { M.lock(); }
~MutexGuard() { M.unlock(); }
diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h
index b039fae..52f133c 100644
--- a/include/llvm/Support/OnDiskHashTable.h
+++ b/include/llvm/Support/OnDiskHashTable.h
@@ -14,8 +14,8 @@
#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
#define LLVM_SUPPORT_ONDISKHASHTABLE_H
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Host.h"
diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h
index 914141a..96afb60 100644
--- a/include/llvm/Support/PrettyStackTrace.h
+++ b/include/llvm/Support/PrettyStackTrace.h
@@ -30,8 +30,8 @@ namespace llvm {
/// virtual stack trace. This gets dumped out if the program crashes.
class PrettyStackTraceEntry {
const PrettyStackTraceEntry *NextEntry;
- PrettyStackTraceEntry(const PrettyStackTraceEntry &) LLVM_DELETED_FUNCTION;
- void operator=(const PrettyStackTraceEntry&) LLVM_DELETED_FUNCTION;
+ PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
+ void operator=(const PrettyStackTraceEntry&) = delete;
public:
PrettyStackTraceEntry();
virtual ~PrettyStackTraceEntry();
diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h
index 8616679..cfdd06c 100644
--- a/include/llvm/Support/Process.h
+++ b/include/llvm/Support/Process.h
@@ -38,111 +38,13 @@ class StringRef;
namespace sys {
-class self_process;
-
-/// \brief Generic base class which exposes information about an operating
-/// system process.
-///
-/// This base class is the core interface behind any OS process. It exposes
-/// methods to query for generic information about a particular process.
-///
-/// Subclasses implement this interface based on the mechanisms available, and
-/// can optionally expose more interfaces unique to certain process kinds.
-class process {
-protected:
- /// \brief Only specific subclasses of process objects can be destroyed.
- virtual ~process();
-
-public:
- /// \brief Operating system specific type to identify a process.
- ///
- /// Note that the windows one is defined to 'unsigned long' as this is the
- /// documented type for DWORD on windows, and we don't want to pull in the
- /// Windows headers here.
-#if defined(LLVM_ON_UNIX)
- typedef pid_t id_type;
-#elif defined(LLVM_ON_WIN32)
- typedef unsigned long id_type; // Must match the type of DWORD.
-#else
-#error Unsupported operating system.
-#endif
-
- /// \brief Get the operating system specific identifier for this process.
- virtual id_type get_id() = 0;
-
- /// \brief Get the user time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_user_time() const = 0;
-
- /// \brief Get the system time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_system_time() const = 0;
-
- /// \brief Get the wall time consumed by this process.
- ///
- /// Note that this is often an approximation and may be zero on platforms
- /// where we don't have good support for the functionality.
- virtual TimeValue get_wall_time() const = 0;
-
- /// \name Static factory routines for processes.
- /// @{
-
- /// \brief Get the process object for the current process.
- static self_process *get_self();
-
- /// @}
-
-};
-
-/// \brief The specific class representing the current process.
-///
-/// The current process can both specialize the implementation of the routines
-/// and can expose certain information not available for other OS processes.
-class self_process : public process {
- friend class process;
-
- /// \brief Private destructor, as users shouldn't create objects of this
- /// type.
- virtual ~self_process();
-
-public:
- id_type get_id() override;
- TimeValue get_user_time() const override;
- TimeValue get_system_time() const override;
- TimeValue get_wall_time() const override;
-
- /// \name Process configuration (sysconf on POSIX)
- /// @{
-
- /// \brief Get the virtual memory page size.
- ///
- /// Query the operating system for this process's page size.
- size_t page_size() const { return PageSize; };
-
- /// @}
-
-private:
- /// \name Cached process state.
- /// @{
-
- /// \brief Cached page size, this cannot vary during the life of the process.
- size_t PageSize;
-
- /// @}
-
- /// \brief Constructor, used by \c process::get_self() only.
- self_process();
-};
-
/// \brief A collection of legacy interfaces for querying information about the
/// current executing process.
class Process {
public:
+ static unsigned getPageSize();
+
/// \brief Return process memory usage.
/// This static function will return the total amount of memory allocated
/// by the process. This only counts the memory allocated via the malloc,
diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h
index b80b855..9a5e421 100644
--- a/include/llvm/Support/RWMutex.h
+++ b/include/llvm/Support/RWMutex.h
@@ -76,8 +76,8 @@ namespace llvm
/// @name Do Not Implement
/// @{
private:
- RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION;
- void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION;
+ RWMutexImpl(const RWMutexImpl & original) = delete;
+ void operator=(const RWMutexImpl &) = delete;
/// @}
};
diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h
index cadc713..7446558 100644
--- a/include/llvm/Support/RandomNumberGenerator.h
+++ b/include/llvm/Support/RandomNumberGenerator.h
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines an abstraction for random number generation (RNG).
-// Note that the current implementation is not cryptographically secure
-// as it uses the C++11 <random> facilities.
+// This file defines an abstraction for deterministic random number
+// generation (RNG). Note that the current implementation is not
+// cryptographically secure as it uses the C++11 <random> facilities.
//
//===----------------------------------------------------------------------===//
@@ -24,33 +24,34 @@
namespace llvm {
/// A random number generator.
-/// Instances of this class should not be shared across threads.
+///
+/// Instances of this class should not be shared across threads. The
+/// seed should be set by passing the -rng-seed=<uint64> option. Use
+/// Module::createRNG to create a new RNG instance for use with that
+/// module.
class RandomNumberGenerator {
public:
- /// Seeds and salts the underlying RNG engine. The salt of type StringRef
- /// is passed into the constructor. The seed can be set on the command
- /// line via -rng-seed=<uint64>.
- /// The reason for the salt is to ensure different random streams even if
- /// the same seed is used for multiple invocations of the compiler.
- /// A good salt value should add additional entropy and be constant across
- /// different machines (i.e., no paths) to allow for reproducible builds.
- /// An instance of this class can be retrieved from the current Module.
- /// \see Module::getRNG
- RandomNumberGenerator(StringRef Salt);
-
/// Returns a random number in the range [0, Max).
- uint64_t next(uint64_t Max);
+ uint_fast64_t operator()();
private:
+ /// Seeds and salts the underlying RNG engine.
+ ///
+ /// This constructor should not be used directly. Instead use
+ /// Module::createRNG to create a new RNG salted with the Module ID.
+ RandomNumberGenerator(StringRef Salt);
+
// 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000
// http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
+ // This RNG is deterministically portable across C++11
+ // implementations.
std::mt19937_64 Generator;
// Noncopyable.
- RandomNumberGenerator(const RandomNumberGenerator &other)
- LLVM_DELETED_FUNCTION;
- RandomNumberGenerator &
- operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION;
+ RandomNumberGenerator(const RandomNumberGenerator &other) = delete;
+ RandomNumberGenerator &operator=(const RandomNumberGenerator &other) = delete;
+
+ friend class Module;
};
}
diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h
index bf533ca..5e5a5a3 100644
--- a/include/llvm/Support/Regex.h
+++ b/include/llvm/Support/Regex.h
@@ -46,7 +46,7 @@ namespace llvm {
/// Compiles the given regular expression \p Regex.
Regex(StringRef Regex, unsigned Flags = NoFlags);
- Regex(const Regex &) LLVM_DELETED_FUNCTION;
+ Regex(const Regex &) = delete;
Regex &operator=(Regex regex) {
std::swap(preg, regex.preg);
std::swap(error, regex.error);
diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h
index b0c2e89..1f81d07 100644
--- a/include/llvm/Support/Registry.h
+++ b/include/llvm/Support/Registry.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-
#include <memory>
namespace llvm {
@@ -42,7 +41,7 @@ namespace llvm {
/// is necessary to define an alternate traits class.
template <typename T>
class RegistryTraits {
- RegistryTraits() LLVM_DELETED_FUNCTION;
+ RegistryTraits() = delete;
public:
typedef SimpleRegistryEntry<T> entry;
@@ -68,7 +67,7 @@ namespace llvm {
class iterator;
private:
- Registry() LLVM_DELETED_FUNCTION;
+ Registry() = delete;
static void Announce(const entry &E) {
for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
@@ -121,6 +120,10 @@ namespace llvm {
static iterator begin() { return iterator(Head); }
static iterator end() { return iterator(nullptr); }
+ static iterator_range<iterator> entries() {
+ return iterator_range<iterator>(begin(), end());
+ }
+
/// Abstract base class for registry listeners, which are informed when new
/// entries are added to the registry. Simply subclass and instantiate:
diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h
index 2bd7e74..a1c4c80 100644
--- a/include/llvm/Support/ScaledNumber.h
+++ b/include/llvm/Support/ScaledNumber.h
@@ -23,7 +23,6 @@
#define LLVM_SUPPORT_SCALEDNUMBER_H
#include "llvm/Support/MathExtras.h"
-
#include <algorithm>
#include <cstdint>
#include <limits>
diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h
index 6cbc1f6..6b1da2a 100644
--- a/include/llvm/Support/Signals.h
+++ b/include/llvm/Support/Signals.h
@@ -39,6 +39,9 @@ namespace sys {
/// @brief Print a stack trace if a fatal signal occurs.
void PrintStackTraceOnErrorSignal();
+ /// Disable all system dialog boxes that appear when the process crashes.
+ void DisableSystemDialogsOnCrash();
+
/// \brief Print the stack trace using the given \c FILE object.
void PrintStackTrace(FILE *);
diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index f9e114b..d492748 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -73,8 +73,8 @@ private:
bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
- SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION;
- void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION;
+ SourceMgr(const SourceMgr&) = delete;
+ void operator=(const SourceMgr&) = delete;
public:
SourceMgr()
: LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {}
diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h
index 313212e..ce693c5 100644
--- a/include/llvm/Support/SpecialCaseList.h
+++ b/include/llvm/Support/SpecialCaseList.h
@@ -49,6 +49,8 @@
#define LLVM_SUPPORT_SPECIALCASELIST_H
#include "llvm/ADT/StringMap.h"
+#include <string>
+#include <vector>
namespace llvm {
class MemoryBuffer;
@@ -57,18 +59,18 @@ class StringRef;
class SpecialCaseList {
public:
- /// Parses the special case list from a file. If Path is empty, returns
- /// an empty special case list. On failure, returns 0 and writes an error
- /// message to string.
- static std::unique_ptr<SpecialCaseList> create(StringRef Path,
- std::string &Error);
+ /// Parses the special case list entries from files. On failure, returns
+ /// 0 and writes an error message to string.
+ static std::unique_ptr<SpecialCaseList>
+ create(const std::vector<std::string> &Paths, std::string &Error);
/// Parses the special case list from a memory buffer. On failure, returns
/// 0 and writes an error message to string.
static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
- std::string &Error);
- /// Parses the special case list from a file. On failure, reports a fatal
- /// error.
- static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path);
+ std::string &Error);
+ /// Parses the special case list entries from files. On failure, reports a
+ /// fatal error.
+ static std::unique_ptr<SpecialCaseList>
+ createOrDie(const std::vector<std::string> &Paths);
~SpecialCaseList();
@@ -81,15 +83,19 @@ public:
StringRef Category = StringRef()) const;
private:
- SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
- SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
+ SpecialCaseList(SpecialCaseList const &) = delete;
+ SpecialCaseList &operator=(SpecialCaseList const &) = delete;
struct Entry;
- StringMap<StringMap<Entry> > Entries;
+ StringMap<StringMap<Entry>> Entries;
+ StringMap<StringMap<std::string>> Regexps;
+ bool IsCompiled;
SpecialCaseList();
/// Parses just-constructed SpecialCaseList entries from a memory buffer.
bool parse(const MemoryBuffer *MB, std::string &Error);
+ /// compile() should be called once, after parsing all the memory buffers.
+ void compile();
};
} // namespace llvm
diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h
index 6957c6e..f914817 100644
--- a/include/llvm/Support/StreamingMemoryObject.h
+++ b/include/llvm/Support/StreamingMemoryObject.h
@@ -65,23 +65,24 @@ private:
// Most of the requests will be small, but we fetch at kChunkSize bytes
// at a time to avoid making too many potentially expensive GetBytes calls
bool fetchToPos(size_t Pos) const {
- if (EOFReached) return Pos < ObjectSize;
+ if (EOFReached)
+ return Pos < ObjectSize;
while (Pos >= BytesRead) {
Bytes.resize(BytesRead + BytesSkipped + kChunkSize);
size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
kChunkSize);
BytesRead += bytes;
- if (BytesRead <= Pos) { // reached EOF/ran out of bytes
+ if (bytes != kChunkSize) { // reached EOF/ran out of bytes
ObjectSize = BytesRead;
EOFReached = true;
- return false;
+ break;
}
}
- return true;
+ return Pos < BytesRead;
}
- StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
- void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
+ StreamingMemoryObject(const StreamingMemoryObject&) = delete;
+ void operator=(const StreamingMemoryObject&) = delete;
};
MemoryObject *getNonStreamedMemoryObject(
diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h
index 3e04653..675adde 100644
--- a/include/llvm/Support/StringPool.h
+++ b/include/llvm/Support/StringPool.h
@@ -29,8 +29,8 @@
#ifndef LLVM_SUPPORT_STRINGPOOL_H
#define LLVM_SUPPORT_STRINGPOOL_H
-#include "llvm/Support/Compiler.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
#include <cassert>
#include <new>
@@ -129,7 +129,7 @@ namespace llvm {
}
inline const char *operator*() const { return begin(); }
- inline LLVM_EXPLICIT operator bool() const { return S != nullptr; }
+ inline explicit operator bool() const { return S != nullptr; }
inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h
index 9c5a3c5..70564be 100644
--- a/include/llvm/Support/SwapByteOrder.h
+++ b/include/llvm/Support/SwapByteOrder.h
@@ -94,6 +94,26 @@ inline signed long long getSwappedBytes(signed long long C) {
return SwapByteOrder_64(C);
}
+inline float getSwappedBytes(float C) {
+ union {
+ uint32_t i;
+ float f;
+ } in, out;
+ in.f = C;
+ out.i = SwapByteOrder_32(in.i);
+ return out.f;
+}
+
+inline float getSwappedBytes(double C) {
+ union {
+ uint64_t i;
+ double d;
+ } in, out;
+ in.d = C;
+ out.i = SwapByteOrder_64(in.i);
+ return out.d;
+}
+
template<typename T>
inline void swapByteOrder(T &Value) {
Value = getSwappedBytes(Value);
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index 8ac4b90..7a71f6d 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CodeGen.h"
#include <cassert>
+#include <memory>
#include <string>
namespace llvm {
@@ -46,6 +47,7 @@ namespace llvm {
class MCRelocationInfo;
class MCTargetAsmParser;
class MCTargetOptions;
+ class MCTargetStreamer;
class TargetMachine;
class TargetOptions;
class raw_ostream;
@@ -61,9 +63,8 @@ namespace llvm {
MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx,
- MCRelocationInfo *RelInfo);
+ void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
/// Target - Wrapper for Target specific information.
///
@@ -99,8 +100,11 @@ namespace llvm {
Reloc::Model RM,
CodeModel::Model CM,
CodeGenOpt::Level OL);
- typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM,
- MCStreamer &Streamer);
+ // If it weren't for layering issues (this header is in llvm/Support, but
+ // depends on MC?) this should take the Streamer by value rather than rvalue
+ // reference.
+ typedef AsmPrinter *(*AsmPrinterCtorTy)(
+ TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer);
typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T,
const MCRegisterInfo &MRI,
StringRef TT,
@@ -135,15 +139,13 @@ namespace llvm {
MCCodeEmitter *CE,
MCAsmBackend *TAB,
bool ShowInst);
- typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx);
+ typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S);
typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT,
MCContext &Ctx);
- typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx,
- MCRelocationInfo *RelInfo);
+ typedef MCSymbolizer *(*MCSymbolizerCtorTy)(
+ StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
private:
/// Next - The next registered target in the linked list, maintained by the
@@ -222,9 +224,9 @@ namespace llvm {
/// AsmStreamer, if registered (default = llvm::createAsmStreamer).
AsmStreamerCtorTy AsmStreamerCtorFn;
- /// Construction function for this target's NullStreamer, if registered
- /// (default = llvm::createNullStreamer).
- NullStreamerCtorTy NullStreamerCtorFn;
+ /// Construction function for this target's null TargetStreamer, if
+ /// registered (default = nullptr).
+ NullTargetStreamerCtorTy NullTargetStreamerCtorFn;
/// MCRelocationInfoCtorFn - Construction function for this target's
/// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
@@ -236,8 +238,8 @@ namespace llvm {
public:
Target()
- : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr),
- MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {}
+ : AsmStreamerCtorFn(nullptr), MCRelocationInfoCtorFn(nullptr),
+ MCSymbolizerCtorFn(nullptr) {}
/// @name Target Information
/// @{
@@ -376,10 +378,11 @@ namespace llvm {
/// createAsmPrinter - Create a target specific assembly printer pass. This
/// takes ownership of the MCStreamer object.
- AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{
+ AsmPrinter *createAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) const {
if (!AsmPrinterCtorFn)
return nullptr;
- return AsmPrinterCtorFn(TM, Streamer);
+ return AsmPrinterCtorFn(TM, std::move(Streamer));
}
MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI,
@@ -446,9 +449,15 @@ namespace llvm {
}
MCStreamer *createNullStreamer(MCContext &Ctx) const {
- if (NullStreamerCtorFn)
- return NullStreamerCtorFn(Ctx);
- return llvm::createNullStreamer(Ctx);
+ MCStreamer *S = llvm::createNullStreamer(Ctx);
+ createNullTargetStreamer(*S);
+ return S;
+ }
+
+ MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) const {
+ if (NullTargetStreamerCtorFn)
+ return NullTargetStreamerCtorFn(S);
+ return nullptr;
}
/// createMCRelocationInfo - Create a target specific MCRelocationInfo.
@@ -474,12 +483,12 @@ namespace llvm {
/// \param RelInfo The relocation information for this target. Takes ownership.
MCSymbolizer *
createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo,
- MCContext *Ctx, MCRelocationInfo *RelInfo) const {
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo,
+ MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo) const {
MCSymbolizerCtorTy Fn =
MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer;
- return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo);
+ return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo));
}
/// @}
@@ -777,8 +786,9 @@ namespace llvm {
T.AsmStreamerCtorFn = Fn;
}
- static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) {
- T.NullStreamerCtorFn = Fn;
+ static void
+ RegisterNullTargetStreamer(Target &T, Target::NullTargetStreamerCtorTy Fn) {
+ T.NullTargetStreamerCtorFn = Fn;
}
/// RegisterMCRelocationInfo - Register an MCRelocationInfo
@@ -1121,8 +1131,9 @@ namespace llvm {
}
private:
- static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) {
- return new AsmPrinterImpl(TM, Streamer);
+ static AsmPrinter *Allocator(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) {
+ return new AsmPrinterImpl(TM, std::move(Streamer));
}
};
diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h
index 7518626..427a67e 100644
--- a/include/llvm/Support/ThreadLocal.h
+++ b/include/llvm/Support/ThreadLocal.h
@@ -36,7 +36,7 @@ namespace llvm {
ThreadLocalImpl();
virtual ~ThreadLocalImpl();
void setInstance(const void* d);
- const void* getInstance();
+ void *getInstance();
void removeInstance();
};
diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h
index 7e87584..3cca1d6 100644
--- a/include/llvm/Support/Threading.h
+++ b/include/llvm/Support/Threading.h
@@ -21,7 +21,8 @@ namespace llvm {
bool llvm_is_multithreaded();
/// llvm_execute_on_thread - Execute the given \p UserFn on a separate
- /// thread, passing it the provided \p UserData.
+ /// thread, passing it the provided \p UserData and waits for thread
+ /// completion.
///
/// This function does not guarantee that the code will actually be executed
/// on a separate thread or honoring the requested stack size, but tries to do
diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h
index 45c1828..442b361 100644
--- a/include/llvm/Support/Timer.h
+++ b/include/llvm/Support/Timer.h
@@ -126,7 +126,7 @@ private:
///
class TimeRegion {
Timer *T;
- TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION;
+ TimeRegion(const TimeRegion &) = delete;
public:
explicit TimeRegion(Timer &t) : T(&t) {
T->startTimer();
@@ -164,8 +164,8 @@ class TimerGroup {
std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
- TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
- void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
+ TimerGroup(const TimerGroup &TG) = delete;
+ void operator=(const TimerGroup &TG) = delete;
public:
explicit TimerGroup(StringRef name);
~TimerGroup();
diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h
index 5a4c273..529284d 100644
--- a/include/llvm/Support/UniqueLock.h
+++ b/include/llvm/Support/UniqueLock.h
@@ -29,8 +29,8 @@ namespace llvm {
MutexT *M;
bool locked;
- unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION;
- void operator=(const unique_lock &) LLVM_DELETED_FUNCTION;
+ unique_lock(const unique_lock &) = delete;
+ void operator=(const unique_lock &) = delete;
public:
unique_lock() : M(nullptr), locked(false) {}
explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h
index b58496b..01e1d92 100644
--- a/include/llvm/Support/Watchdog.h
+++ b/include/llvm/Support/Watchdog.h
@@ -29,8 +29,8 @@ namespace llvm {
~Watchdog();
private:
// Noncopyable.
- Watchdog(const Watchdog &other) LLVM_DELETED_FUNCTION;
- Watchdog &operator=(const Watchdog &other) LLVM_DELETED_FUNCTION;
+ Watchdog(const Watchdog &other) = delete;
+ Watchdog &operator=(const Watchdog &other) = delete;
};
}
}
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index 023dcee7..78829f8 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -447,6 +447,7 @@ public:
virtual void beginEnumScalar() = 0;
virtual bool matchEnumScalar(const char*, bool) = 0;
+ virtual bool matchEnumFallback() = 0;
virtual void endEnumScalar() = 0;
virtual bool beginBitSetScalar(bool &) = 0;
@@ -472,6 +473,16 @@ public:
}
}
+ template <typename FBT, typename T>
+ void enumFallback(T &Val) {
+ if ( matchEnumFallback() ) {
+ // FIXME: Force integral conversion to allow strong typedefs to convert.
+ FBT Res = (uint64_t)Val;
+ yamlize(*this, Res, true);
+ Val = (uint64_t)Res;
+ }
+ }
+
template <typename T>
void bitSetCase(T &Val, const char* Str, const T ConstVal) {
if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
@@ -532,7 +543,7 @@ public:
void mapOptional(const char* Key, T& Val, const T& Default) {
this->processKeyWithDefault(Key, Val, Default, false);
}
-
+
private:
template <typename T>
void processKeyWithDefault(const char *Key, Optional<T> &Val,
@@ -706,7 +717,7 @@ struct ScalarTraits<StringRef> {
static StringRef input(StringRef, void*, StringRef &);
static bool mustQuote(StringRef S) { return needsQuotes(S); }
};
-
+
template<>
struct ScalarTraits<std::string> {
static void output(const std::string &, void*, llvm::raw_ostream &);
@@ -899,6 +910,7 @@ private:
void endFlowSequence() override;
void beginEnumScalar() override;
bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
void endEnumScalar() override;
bool beginBitSetScalar(bool &) override;
bool bitSetMatch(const char *, bool ) override;
@@ -1026,6 +1038,7 @@ public:
void endFlowSequence() override;
void beginEnumScalar() override;
bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
void endEnumScalar() override;
bool beginBitSetScalar(bool &) override;
bool bitSetMatch(const char *, bool ) override;
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index c9ef637..94686d9 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -38,8 +38,8 @@ namespace llvm {
/// a chunk at a time.
class raw_ostream {
private:
- void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION;
- raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION;
+ void operator=(const raw_ostream &) = delete;
+ raw_ostream(const raw_ostream &) = delete;
/// The buffer is handled in such a way that the buffer is
/// uninitialized, unbuffered, or out of space when OutBufCur >=
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 70953a9..45465ae 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -28,9 +28,17 @@ namespace llvm {
/// type can be copied around with memcpy instead of running ctors etc.
template <typename T>
struct isPodLike {
-#if __has_feature(is_trivially_copyable)
+ // std::is_trivially_copyable is available in libc++ with clang, libstdc++
+ // that comes with GCC 5.
+#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
// If the compiler supports the is_trivially_copyable trait use it, as it
// matches the definition of isPodLike closely.
+ static const bool value = std::is_trivially_copyable<T>::value;
+#elif __has_feature(is_trivially_copyable)
+ // Use the internal name if the compiler supports is_trivially_copyable but we
+ // don't know if the standard library does. This is the case for clang in
+ // conjunction with libstdc++ from GCC 4.x.
static const bool value = __is_trivially_copyable(T);
#else
// If we don't know anything else, we can (at least) assume that all non-class
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 8c5452e..e8d22d9 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -454,8 +454,8 @@ protected:
private:
const InitKind Kind;
- Init(const Init &) LLVM_DELETED_FUNCTION;
- Init &operator=(const Init &) LLVM_DELETED_FUNCTION;
+ Init(const Init &) = delete;
+ Init &operator=(const Init &) = delete;
virtual void anchor();
public:
@@ -561,8 +561,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
class TypedInit : public Init {
RecTy *Ty;
- TypedInit(const TypedInit &Other) LLVM_DELETED_FUNCTION;
- TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION;
+ TypedInit(const TypedInit &Other) = delete;
+ TypedInit &operator=(const TypedInit &Other) = delete;
protected:
explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {}
@@ -596,8 +596,8 @@ public:
///
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
- UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION;
- UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION;
+ UnsetInit(const UnsetInit &) = delete;
+ UnsetInit &operator=(const UnsetInit &Other) = delete;
void anchor() override;
public:
@@ -624,8 +624,8 @@ class BitInit : public Init {
bool Value;
explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
- BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION;
- BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION;
+ BitInit(const BitInit &Other) = delete;
+ BitInit &operator=(BitInit &Other) = delete;
void anchor() override;
public:
@@ -658,8 +658,8 @@ class BitsInit : public TypedInit, public FoldingSetNode {
: TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())),
Bits(Range.begin(), Range.end()) {}
- BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION;
- BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION;
+ BitsInit(const BitsInit &Other) = delete;
+ BitsInit &operator=(const BitsInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -713,8 +713,8 @@ class IntInit : public TypedInit {
explicit IntInit(int64_t V)
: TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
- IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION;
- IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION;
+ IntInit(const IntInit &Other) = delete;
+ IntInit &operator=(const IntInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -753,8 +753,8 @@ class StringInit : public TypedInit {
explicit StringInit(const std::string &V)
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
- StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION;
- StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION;
+ StringInit(const StringInit &Other) = delete;
+ StringInit &operator=(const StringInit &Other) = delete;
void anchor() override;
public:
@@ -798,8 +798,8 @@ private:
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
Values(Range.begin(), Range.end()) {}
- ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION;
- ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION;
+ ListInit(const ListInit &Other) = delete;
+ ListInit &operator=(const ListInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -855,8 +855,8 @@ public:
/// OpInit - Base class for operators
///
class OpInit : public TypedInit {
- OpInit(const OpInit &Other) LLVM_DELETED_FUNCTION;
- OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION;
+ OpInit(const OpInit &Other) = delete;
+ OpInit &operator=(OpInit &Other) = delete;
protected:
explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {}
@@ -899,8 +899,8 @@ private:
UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
: OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {}
- UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
- UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
+ UnOpInit(const UnOpInit &Other) = delete;
+ UnOpInit &operator=(const UnOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -946,8 +946,8 @@ private:
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {}
- BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
- BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
+ BinOpInit(const BinOpInit &Other) = delete;
+ BinOpInit &operator=(const BinOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1000,8 +1000,8 @@ private:
RecTy *Type) :
OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
- TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
- TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
+ TernOpInit(const TernOpInit &Other) = delete;
+ TernOpInit &operator=(const TernOpInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1058,8 +1058,8 @@ class VarInit : public TypedInit {
explicit VarInit(Init *VN, RecTy *T)
: TypedInit(IK_VarInit, T), VarName(VN) {}
- VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION;
- VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION;
+ VarInit(const VarInit &Other) = delete;
+ VarInit &operator=(const VarInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1111,8 +1111,8 @@ class VarBitInit : public Init {
"Illegal VarBitInit expression!");
}
- VarBitInit(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
- VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
+ VarBitInit(const VarBitInit &Other) = delete;
+ VarBitInit &operator=(const VarBitInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1150,8 +1150,8 @@ class VarListElementInit : public TypedInit {
"Illegal VarBitInit expression!");
}
- VarListElementInit(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
- void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
+ VarListElementInit(const VarListElementInit &Other) = delete;
+ void operator=(const VarListElementInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1186,8 +1186,8 @@ class DefInit : public TypedInit {
DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
friend class Record;
- DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION;
- DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION;
+ DefInit(const DefInit &Other) = delete;
+ DefInit &operator=(const DefInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1233,8 +1233,8 @@ class FieldInit : public TypedInit {
assert(getType() && "FieldInit with non-record type!");
}
- FieldInit(const FieldInit &Other) LLVM_DELETED_FUNCTION;
- FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION;
+ FieldInit(const FieldInit &Other) = delete;
+ FieldInit &operator=(const FieldInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1276,8 +1276,8 @@ class DagInit : public TypedInit, public FoldingSetNode {
Args(ArgRange.begin(), ArgRange.end()),
ArgNames(NameRange.begin(), NameRange.end()) {}
- DagInit(const DagInit &Other) LLVM_DELETED_FUNCTION;
- DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION;
+ DagInit(const DagInit &Other) = delete;
+ DagInit &operator=(const DagInit &Other) = delete;
public:
static bool classof(const Init *I) {
@@ -1663,7 +1663,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Record &R);
struct MultiClass {
Record Rec; // Placeholder for template args and Name.
- typedef std::vector<Record*> RecordVector;
+ typedef std::vector<std::unique_ptr<Record>> RecordVector;
RecordVector DefPrototypes;
void dump() const;
@@ -1688,15 +1688,13 @@ public:
auto I = Defs.find(Name);
return I == Defs.end() ? nullptr : I->second.get();
}
- void addClass(Record *_R) {
- std::unique_ptr<Record> R(_R);
+ void addClass(std::unique_ptr<Record> R) {
bool Ins = Classes.insert(std::make_pair(R->getName(),
std::move(R))).second;
(void)Ins;
assert(Ins && "Class already exists");
}
- void addDef(Record *_R) {
- std::unique_ptr<Record> R(_R);
+ void addDef(std::unique_ptr<Record> R) {
bool Ins = Defs.insert(std::make_pair(R->getName(),
std::move(R))).second;
(void)Ins;
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 902647e..3e65a5d 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -396,12 +396,9 @@ class Instruction {
// hasSideEffects - The instruction has side effects that are not
// captured by any operands of the instruction or other flags.
//
- // neverHasSideEffects (deprecated) - Set on an instruction with no pattern
- // if it has no side effects. This is now equivalent to setting
- // "hasSideEffects = 0".
bit hasSideEffects = ?;
- bit neverHasSideEffects = 0;
-
+ bit hasTwoExplicitDefs = 0; // Does this instruction have 2 explicit
+ // destinations?
// Is this instruction a "real" instruction (with a distinct machine
// encoding), or is it a pseudo instruction used for codegen modeling
// purposes.
@@ -628,6 +625,9 @@ class RegisterOperand<RegisterClass regclass, string pm = "printOperand">
// can match a subset of some other class, in which case the AsmOperandClass
// should declare the other operand as one of its super classes.
AsmOperandClass ParserMatchClass;
+
+ string OperandNamespace = "MCOI";
+ string OperandType = "OPERAND_REGISTER";
}
let OperandType = "OPERAND_IMMEDIATE" in {
@@ -734,7 +734,7 @@ def INLINEASM : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1; // Note side effect is encoded in an operand.
+ let hasSideEffects = 0; // Note side effect is encoded in an operand.
}
def CFI_INSTRUCTION : Instruction {
let OutOperandList = (outs);
@@ -761,26 +761,26 @@ def KILL : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def EXTRACT_SUBREG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def INSERT_SUBREG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let Constraints = "$supersrc = $dst";
}
def IMPLICIT_DEF : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isReMaterializable = 1;
let isAsCheapAsAMove = 1;
}
@@ -788,33 +788,33 @@ def SUBREG_TO_REG : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def COPY_TO_REGCLASS : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$src, i32imm:$regclass);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def DBG_VALUE : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "DBG_VALUE";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def REG_SEQUENCE : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$supersrc, variable_ops);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def COPY : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$src);
let AsmString = "";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
let isAsCheapAsAMove = 1;
}
def BUNDLE : Instruction {
@@ -826,13 +826,13 @@ def LIFETIME_START : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins i32imm:$id);
let AsmString = "LIFETIME_START";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def LIFETIME_END : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins i32imm:$id);
let AsmString = "LIFETIME_END";
- let neverHasSideEffects = 1;
+ let hasSideEffects = 0;
}
def STACKMAP : Instruction {
let OutOperandList = (outs);
@@ -849,6 +849,15 @@ def PATCHPOINT : Instruction {
let mayLoad = 1;
let usesCustomInserter = 1;
}
+def STATEPOINT : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins variable_ops);
+ let usesCustomInserter = 1;
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+ let isCall = 1;
+}
def LOAD_STACK_GUARD : Instruction {
let OutOperandList = (outs ptr_rc:$dst);
let InOperandList = (ins);
@@ -857,6 +866,15 @@ def LOAD_STACK_GUARD : Instruction {
let hasSideEffects = 0;
bit isPseudo = 1;
}
+def FRAME_ALLOC : Instruction {
+ // This instruction is really just a label. It has to be part of the chain so
+ // that it doesn't get dropped from the DAG, but it produces nothing and has
+ // no side effects.
+ let OutOperandList = (outs);
+ let InOperandList = (ins ptr_rc:$symbol, i32imm:$id);
+ let hasSideEffects = 0;
+ let hasCtrlDep = 1;
+}
}
//===----------------------------------------------------------------------===//
@@ -1005,9 +1023,6 @@ class AsmWriter {
// will specify which alternative to use. For example "{x|y|z}" with Variant
// == 1, will expand to "y".
int Variant = 0;
-
- // OperandSpacing - Space between operand columns.
- int OperandSpacing = -1;
}
def DefaultAsmWriter : AsmWriter;
diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h
index a0f2674..9071bfe 100644
--- a/include/llvm/Target/TargetCallingConv.h
+++ b/include/llvm/Target/TargetCallingConv.h
@@ -134,6 +134,8 @@ namespace ISD {
/// Index original Function's argument.
unsigned OrigArgIndex;
+ /// Sentinel value for implicit machine-level input arguments.
+ static const unsigned NoArgIndex = UINT_MAX;
/// Offset in bytes of current input value relative to the beginning of
/// original argument. E.g. if argument was splitted into four 32 bit
@@ -147,6 +149,15 @@ namespace ISD {
VT = vt.getSimpleVT();
ArgVT = argvt;
}
+
+ bool isOrigArg() const {
+ return OrigArgIndex != NoArgIndex;
+ }
+
+ unsigned getOrigArgIndex() const {
+ assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
+ return OrigArgIndex;
+ }
};
/// OutputArg - This struct carries flags and a value for a
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index bfddd06..f17640f 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/include/llvm/Target/TargetFrameLowering.h
@@ -142,6 +142,10 @@ public:
/// the assembly prologue to explicitly handle the stack.
virtual void adjustForHiPEPrologue(MachineFunction &MF) const { }
+ /// Adjust the prologue to add an allocation at a fixed offset from the frame
+ /// pointer.
+ virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { }
+
/// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
/// saved registers and returns true if it isn't possible / profitable to do
/// so by issuing a series of store instructions via
@@ -189,6 +193,11 @@ public:
return hasReservedCallFrame(MF) || hasFP(MF);
}
+ // needsFrameIndexResolution - Do we need to perform FI resolution for
+ // this function. Normally, this is required only when the function
+ // has any stack objects. However, targets may want to override this.
+ virtual bool needsFrameIndexResolution(const MachineFunction &MF) const;
+
/// getFrameIndexOffset - Returns the displacement from the frame register to
/// the stack frame of the specified index.
virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
@@ -199,6 +208,16 @@ public:
virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
unsigned &FrameReg) const;
+ /// Same as above, except that the 'base register' will always be RSP, not
+ /// RBP on x86. This is used exclusively for lowering STATEPOINT nodes.
+ /// TODO: This should really be a parameterizable choice.
+ virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
+ unsigned &FrameReg) const {
+ // default to calling normal version, we override this on x86 only
+ llvm_unreachable("unimplemented for non-x86");
+ return 0;
+ }
+
/// processFunctionBeforeCalleeSavedScan - This method is called immediately
/// before PrologEpilogInserter scans the physical registers used to determine
/// what callee saved registers should be spilled. This method is optional.
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index a37a7f9..247f9d8 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -14,10 +14,10 @@
#ifndef LLVM_TARGET_TARGETINSTRINFO_H
#define LLVM_TARGET_TARGETINSTRINFO_H
-#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/MachineCombinerPattern.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
@@ -50,8 +50,8 @@ template<class T> class SmallVectorImpl;
/// TargetInstrInfo - Interface to description of machine instruction set
///
class TargetInstrInfo : public MCInstrInfo {
- TargetInstrInfo(const TargetInstrInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetInstrInfo &) LLVM_DELETED_FUNCTION;
+ TargetInstrInfo(const TargetInstrInfo &) = delete;
+ void operator=(const TargetInstrInfo &) = delete;
public:
TargetInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1)
: CallFrameSetupOpcode(CFSetupOpcode),
@@ -109,6 +109,12 @@ public:
int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
+ /// Returns the actual stack pointer adjustment made by an instruction
+ /// as part of a call sequence. By default, only call frame setup/destroy
+ /// instructions adjust the stack, but targets may want to override this
+ /// to enable more fine-grained adjustment, or adjust by a different value.
+ virtual int getSPAdjust(const MachineInstr *MI) const;
+
/// isCoalescableExtInstr - Return true if the instruction is a "coalescable"
/// extension instruction. That is, it's like a copy where it's legal for the
/// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns
@@ -597,9 +603,12 @@ public:
/// a side.
///
/// @param MI Optimizable select instruction.
+ /// @param NewMIs Set that record all MIs in the basic block up to \p
+ /// MI. Has to be updated with any newly created MI or deleted ones.
/// @param PreferFalse Try to optimize FalseOp instead of TrueOp.
/// @returns Optimized instruction or NULL.
virtual MachineInstr *optimizeSelect(MachineInstr *MI,
+ SmallPtrSetImpl<MachineInstr *> &NewMIs,
bool PreferFalse = false) const {
// This function must be implemented if Optimizable is ever set.
llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!");
diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h
index 71c0166..c630f5b 100644
--- a/include/llvm/Target/TargetIntrinsicInfo.h
+++ b/include/llvm/Target/TargetIntrinsicInfo.h
@@ -28,8 +28,8 @@ class Type;
/// TargetIntrinsicInfo - Interface to description of machine instruction set
///
class TargetIntrinsicInfo {
- TargetIntrinsicInfo(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION;
+ TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete;
+ void operator=(const TargetIntrinsicInfo &) = delete;
public:
TargetIntrinsicInfo();
virtual ~TargetIntrinsicInfo();
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 882dab4..4118917 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -30,9 +30,9 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/IRBuilder.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetCallingConv.h"
#include "llvm/Target/TargetMachine.h"
@@ -51,6 +51,7 @@ namespace llvm {
class MachineFunction;
class MachineInstr;
class MachineJumpTableInfo;
+ class MachineLoop;
class Mangler;
class MCContext;
class MCExpr;
@@ -76,8 +77,8 @@ namespace llvm {
/// This base class for TargetLowering contains the SelectionDAG-independent
/// parts that can be used from the rest of CodeGen.
class TargetLoweringBase {
- TargetLoweringBase(const TargetLoweringBase&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLoweringBase&) LLVM_DELETED_FUNCTION;
+ TargetLoweringBase(const TargetLoweringBase&) = delete;
+ void operator=(const TargetLoweringBase&) = delete;
public:
/// This enum indicates whether operations are valid for a target, and if not,
@@ -148,9 +149,6 @@ protected:
public:
const TargetMachine &getTargetMachine() const { return TM; }
const DataLayout *getDataLayout() const { return DL; }
- const TargetLoweringObjectFile &getObjFileLowering() const {
- return *TM.getObjFileLowering();
- }
bool isBigEndian() const { return !IsLittleEndian; }
bool isLittleEndian() const { return IsLittleEndian; }
@@ -216,6 +214,11 @@ public:
/// several shifts, adds, and multiplies for this target.
bool isIntDivCheap() const { return IntDivIsCheap; }
+ /// Return true if sqrt(x) is as cheap or cheaper than 1 / rsqrt(x)
+ bool isFsqrtCheap() const {
+ return FsqrtIsCheap;
+ }
+
/// Returns true if target has indicated at least one type should be bypassed.
bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); }
@@ -249,6 +252,16 @@ public:
return true;
}
+ /// \brief Return true if it is cheap to speculate a call to intrinsic cttz.
+ virtual bool isCheapToSpeculateCttz() const {
+ return false;
+ }
+
+ /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz.
+ virtual bool isCheapToSpeculateCtlz() const {
+ return false;
+ }
+
/// \brief Return if the target supports combining a
/// chain like:
/// \code
@@ -264,6 +277,11 @@ public:
return MaskAndBranchFoldingIsLegal;
}
+ /// \brief Return true if the target wants to use the optimization that
+ /// turns ext(promotableInst1(...(promotableInstN(load)))) into
+ /// promotedInst1(...(promotedInstN(ext(load)))).
+ bool enableExtLdPromotion() const { return EnableExtLdPromotion; }
+
/// Return true if the target can combine store(extractelement VectorTy,
/// Idx).
/// \p Cost[out] gives the cost of that transformation when this is true.
@@ -541,18 +559,27 @@ public:
/// Return how this load with extension should be treated: either it is legal,
/// needs to be promoted to a larger size, needs to be expanded to some other
/// code sequence, or the target has a custom expander for it.
- LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const {
- if (VT.isExtended()) return Expand;
- unsigned I = (unsigned) VT.getSimpleVT().SimpleTy;
- assert(ExtType < ISD::LAST_LOADEXT_TYPE && I < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
- return (LegalizeAction)LoadExtActions[I][ExtType];
+ LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ if (ValVT.isExtended() || MemVT.isExtended()) return Expand;
+ unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy;
+ unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy;
+ assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::LAST_VALUETYPE &&
+ MemI < MVT::LAST_VALUETYPE && "Table isn't big enough!");
+ return (LegalizeAction)LoadExtActions[ValI][MemI][ExtType];
}
/// Return true if the specified load with extension is legal on this target.
- bool isLoadExtLegal(unsigned ExtType, EVT VT) const {
- return VT.isSimple() &&
- getLoadExtAction(ExtType, VT.getSimpleVT()) == Legal;
+ bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ return ValVT.isSimple() && MemVT.isSimple() &&
+ getLoadExtAction(ExtType, ValVT, MemVT) == Legal;
+ }
+
+ /// Return true if the specified load with extension is legal or custom
+ /// on this target.
+ bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const {
+ return ValVT.isSimple() && MemVT.isSimple() &&
+ (getLoadExtAction(ExtType, ValVT, MemVT) == Legal ||
+ getLoadExtAction(ExtType, ValVT, MemVT) == Custom);
}
/// Return how this store with truncation should be treated: either it is
@@ -579,7 +606,7 @@ public:
/// sequence, or the target has a custom expander for it.
LegalizeAction
getIndexedLoadAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE &&
+ assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() &&
"Table isn't big enough!");
unsigned Ty = (unsigned)VT.SimpleTy;
return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4);
@@ -597,7 +624,7 @@ public:
/// sequence, or the target has a custom expander for it.
LegalizeAction
getIndexedStoreAction(unsigned IdxMode, MVT VT) const {
- assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE &&
+ assert(IdxMode < ISD::LAST_INDEXED_MODE && VT.isValid() &&
"Table isn't big enough!");
unsigned Ty = (unsigned)VT.SimpleTy;
return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f);
@@ -753,6 +780,16 @@ public:
/// reduce runtime.
virtual bool ShouldShrinkFPConstant(EVT) const { return true; }
+ // Return true if it is profitable to reduce the given load node to a smaller
+ // type.
+ //
+ // e.g. (i16 (trunc (i32 (load x))) -> i16 load x should be performed
+ virtual bool shouldReduceLoadWidth(SDNode *Load,
+ ISD::LoadExtType ExtTy,
+ EVT NewVT) const {
+ return true;
+ }
+
/// When splitting a value of the specified type into parts, does the Lo
/// or Hi part come first? This usually follows the endianness, except
/// for ppcf128, where the Hi part always comes first.
@@ -904,7 +941,7 @@ public:
}
/// Return the preferred loop alignment.
- unsigned getPrefLoopAlignment() const {
+ virtual unsigned getPrefLoopAlignment(MachineLoop *ML = nullptr) const {
return PrefLoopAlignment;
}
@@ -922,12 +959,6 @@ public:
return false;
}
- /// Returns the maximal possible offset which can be used for loads / stores
- /// from the global.
- virtual unsigned getMaximalGlobalOffset() const {
- return 0;
- }
-
/// Returns true if a cast between SrcAS and DestAS is a noop.
virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const {
return false;
@@ -1057,10 +1088,6 @@ public:
// TargetLowering Configuration Methods - These methods should be invoked by
// the derived class constructor to configure this object for the target.
//
-
- /// \brief Reset the operation actions based on target options.
- virtual void resetOperationActions() {}
-
protected:
/// Specify how the target extends the result of integer and floating point
/// boolean values from i1 to a wider type. See getBooleanContents.
@@ -1156,7 +1183,11 @@ protected:
/// possible, should be replaced by an alternate sequence of instructions not
/// containing an integer divide.
void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; }
-
+
+ /// Tells the code generator that fsqrt is cheap, and should not be replaced
+ /// with an alternative sequence of instructions.
+ void setFsqrtIsCheap(bool isCheap = true) { FsqrtIsCheap = isCheap; }
+
/// Tells the code generator that this target supports floating point
/// exceptions and cares about preserving floating point exception behavior.
void setHasFloatingPointExceptions(bool FPExceptions = true) {
@@ -1194,12 +1225,12 @@ protected:
/// Return the largest legal super-reg register class of the register class
/// for the specified type and its associated "cost".
- virtual std::pair<const TargetRegisterClass*, uint8_t>
- findRepresentativeClass(MVT VT) const;
+ virtual std::pair<const TargetRegisterClass *, uint8_t>
+ findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const;
/// Once all of the register classes are added, this allows us to compute
/// derived properties we expose.
- void computeRegisterProperties();
+ void computeRegisterProperties(const TargetRegisterInfo *TRI);
/// Indicate that the specified operation does not work with the specified
/// type and indicate what to do about it.
@@ -1211,19 +1242,18 @@ protected:
/// Indicate that the specified load with extension does not work with the
/// specified type and indicate what to do about it.
- void setLoadExtAction(unsigned ExtType, MVT VT,
+ void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT,
LegalizeAction Action) {
- assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
- LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action;
+ assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() &&
+ MemVT.isValid() && "Table isn't big enough!");
+ LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy][ExtType] = (uint8_t)Action;
}
/// Indicate that the specified truncating store does not work with the
/// specified type and indicate what to do about it.
void setTruncStoreAction(MVT ValVT, MVT MemVT,
LegalizeAction Action) {
- assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE &&
- "Table isn't big enough!");
+ assert(ValVT.isValid() && MemVT.isValid() && "Table isn't big enough!");
TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action;
}
@@ -1234,7 +1264,7 @@ protected:
/// TargetLowering.cpp
void setIndexedLoadAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE &&
+ assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE &&
(unsigned)Action < 0xf && "Table isn't big enough!");
// Load action are kept in the upper half.
IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0;
@@ -1248,7 +1278,7 @@ protected:
/// TargetLowering.cpp
void setIndexedStoreAction(unsigned IdxMode, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE &&
+ assert(VT.isValid() && IdxMode < ISD::LAST_INDEXED_MODE &&
(unsigned)Action < 0xf && "Table isn't big enough!");
// Store action are kept in the lower half.
IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f;
@@ -1259,8 +1289,7 @@ protected:
/// target and indicate what to do about it.
void setCondCodeAction(ISD::CondCode CC, MVT VT,
LegalizeAction Action) {
- assert(VT < MVT::LAST_VALUETYPE &&
- (unsigned)CC < array_lengthof(CondCodeActions) &&
+ assert(VT.isValid() && (unsigned)CC < array_lengthof(CondCodeActions) &&
"Table isn't big enough!");
/// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 32-bit
/// value and the upper 27 bits index into the second dimension of the array
@@ -1311,7 +1340,8 @@ protected:
/// Set the target's preferred loop alignment. Default alignment is zero, it
/// means the target does not care about loop alignment. The alignment is
- /// specified in log2(bytes).
+ /// specified in log2(bytes). The target may also override
+ /// getPrefLoopAlignment to provide per-loop values.
void setPrefLoopAlignment(unsigned Align) {
PrefLoopAlignment = Align;
}
@@ -1420,6 +1450,8 @@ public:
return false;
}
+ virtual bool isProfitableToHoist(Instruction *I) const { return true; }
+
/// Return true if any actual instruction that defines a value of type Ty1
/// implicitly zero-extends the value to Ty2 in the result register.
///
@@ -1474,6 +1506,18 @@ public:
return isZExtFree(Val.getValueType(), VT2);
}
+ /// Return true if an fpext operation is free (for instance, because
+ /// single-precision floating-point numbers are implicitly extended to
+ /// double-precision).
+ virtual bool isFPExtFree(EVT VT) const {
+ assert(VT.isFloatingPoint());
+ return false;
+ }
+
+ /// Return true if folding a vector load into ExtVal (a sign, zero, or any
+ /// extend node) is profitable.
+ virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; }
+
/// Return true if an fneg operation is free to the point where it is never
/// worthwhile to replace it with a bitwise operation.
virtual bool isFNegFree(EVT VT) const {
@@ -1516,6 +1560,15 @@ public:
Type *Ty) const {
return false;
}
+
+ /// Return true if EXTRACT_SUBVECTOR is cheap for this result type
+ /// with this index. This is needed because EXTRACT_SUBVECTOR usually
+ /// has custom lowering that depends on the index of the first element,
+ /// and only the target knows which lowering is cheap.
+ virtual bool isExtractSubvectorCheap(EVT ResVT, unsigned Index) const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
// Runtime Library hooks
//
@@ -1582,6 +1635,9 @@ private:
/// unconditionally.
bool IntDivIsCheap;
+ // Don't expand fsqrt with an approximation based on the inverse sqrt.
+ bool FsqrtIsCheap;
+
/// Tells the code generator to bypass slow divide or remainder
/// instructions. For example, BypassSlowDivWidths[32,8] tells the code
/// generator to bypass 32-bit integer div/rem with an 8-bit unsigned integer
@@ -1703,7 +1759,8 @@ private:
/// For each load extension type and each value type, keep a LegalizeAction
/// that indicates how instruction selection should deal with a load of a
/// specific value type and extension type.
- uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE];
+ uint8_t LoadExtActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]
+ [ISD::LAST_LOADEXT_TYPE];
/// For each value type pair keep a LegalizeAction that indicates whether a
/// truncating store of a specific value type and truncating type is legal.
@@ -1727,136 +1784,8 @@ private:
ValueTypeActionImpl ValueTypeActions;
-public:
- LegalizeKind
- getTypeConversion(LLVMContext &Context, EVT VT) const {
- // If this is a simple type, use the ComputeRegisterProp mechanism.
- if (VT.isSimple()) {
- MVT SVT = VT.getSimpleVT();
- assert((unsigned)SVT.SimpleTy < array_lengthof(TransformToType));
- MVT NVT = TransformToType[SVT.SimpleTy];
- LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT);
-
- assert(
- (LA == TypeLegal || LA == TypeSoftenFloat ||
- ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger)
- && "Promote may not follow Expand or Promote");
-
- if (LA == TypeSplitVector)
- return LegalizeKind(LA, EVT::getVectorVT(Context,
- SVT.getVectorElementType(),
- SVT.getVectorNumElements()/2));
- if (LA == TypeScalarizeVector)
- return LegalizeKind(LA, SVT.getVectorElementType());
- return LegalizeKind(LA, NVT);
- }
-
- // Handle Extended Scalar Types.
- if (!VT.isVector()) {
- assert(VT.isInteger() && "Float types must be simple");
- unsigned BitSize = VT.getSizeInBits();
- // First promote to a power-of-two size, then expand if necessary.
- if (BitSize < 8 || !isPowerOf2_32(BitSize)) {
- EVT NVT = VT.getRoundIntegerType(Context);
- assert(NVT != VT && "Unable to round integer VT");
- LegalizeKind NextStep = getTypeConversion(Context, NVT);
- // Avoid multi-step promotion.
- if (NextStep.first == TypePromoteInteger) return NextStep;
- // Return rounded integer type.
- return LegalizeKind(TypePromoteInteger, NVT);
- }
-
- return LegalizeKind(TypeExpandInteger,
- EVT::getIntegerVT(Context, VT.getSizeInBits()/2));
- }
-
- // Handle vector types.
- unsigned NumElts = VT.getVectorNumElements();
- EVT EltVT = VT.getVectorElementType();
-
- // Vectors with only one element are always scalarized.
- if (NumElts == 1)
- return LegalizeKind(TypeScalarizeVector, EltVT);
-
- // Try to widen vector elements until the element type is a power of two and
- // promote it to a legal type later on, for example:
- // <3 x i8> -> <4 x i8> -> <4 x i32>
- if (EltVT.isInteger()) {
- // Vectors with a number of elements that is not a power of two are always
- // widened, for example <3 x i8> -> <4 x i8>.
- if (!VT.isPow2VectorType()) {
- NumElts = (unsigned)NextPowerOf2(NumElts);
- EVT NVT = EVT::getVectorVT(Context, EltVT, NumElts);
- return LegalizeKind(TypeWidenVector, NVT);
- }
-
- // Examine the element type.
- LegalizeKind LK = getTypeConversion(Context, EltVT);
-
- // If type is to be expanded, split the vector.
- // <4 x i140> -> <2 x i140>
- if (LK.first == TypeExpandInteger)
- return LegalizeKind(TypeSplitVector,
- EVT::getVectorVT(Context, EltVT, NumElts / 2));
-
- // Promote the integer element types until a legal vector type is found
- // or until the element integer type is too big. If a legal type was not
- // found, fallback to the usual mechanism of widening/splitting the
- // vector.
- EVT OldEltVT = EltVT;
- while (1) {
- // Increase the bitwidth of the element to the next pow-of-two
- // (which is greater than 8 bits).
- EltVT = EVT::getIntegerVT(Context, 1 + EltVT.getSizeInBits()
- ).getRoundIntegerType(Context);
-
- // Stop trying when getting a non-simple element type.
- // Note that vector elements may be greater than legal vector element
- // types. Example: X86 XMM registers hold 64bit element on 32bit
- // systems.
- if (!EltVT.isSimple()) break;
-
- // Build a new vector type and check if it is legal.
- MVT NVT = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts);
- // Found a legal promoted vector type.
- if (NVT != MVT() && ValueTypeActions.getTypeAction(NVT) == TypeLegal)
- return LegalizeKind(TypePromoteInteger,
- EVT::getVectorVT(Context, EltVT, NumElts));
- }
-
- // Reset the type to the unexpanded type if we did not find a legal vector
- // type with a promoted vector element type.
- EltVT = OldEltVT;
- }
-
- // Try to widen the vector until a legal type is found.
- // If there is no wider legal type, split the vector.
- while (1) {
- // Round up to the next power of 2.
- NumElts = (unsigned)NextPowerOf2(NumElts);
-
- // If there is no simple vector type with this many elements then there
- // cannot be a larger legal vector type. Note that this assumes that
- // there are no skipped intermediate vector types in the simple types.
- if (!EltVT.isSimple()) break;
- MVT LargerVector = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts);
- if (LargerVector == MVT()) break;
-
- // If this type is legal then widen the vector.
- if (ValueTypeActions.getTypeAction(LargerVector) == TypeLegal)
- return LegalizeKind(TypeWidenVector, LargerVector);
- }
-
- // Widen odd vectors to next power of two.
- if (!VT.isPow2VectorType()) {
- EVT NVT = VT.getPow2VectorType(Context);
- return LegalizeKind(TypeWidenVector, NVT);
- }
-
- // Vectors with illegal element types are expanded.
- EVT NVT = EVT::getVectorVT(Context, EltVT, VT.getVectorNumElements() / 2);
- return LegalizeKind(TypeSplitVector, NVT);
- }
+private:
+ LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const;
private:
std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses;
@@ -1944,6 +1873,9 @@ protected:
/// a mask of a single bit, a compare, and a branch into a single instruction.
bool MaskAndBranchFoldingIsLegal;
+ /// \see enableExtLdPromotion.
+ bool EnableExtLdPromotion;
+
protected:
/// Return true if the value types that can be represented by the specified
/// register class are all legal.
@@ -1960,8 +1892,8 @@ protected:
/// This class also defines callbacks that targets must implement to lower
/// target-specific constructs to SelectionDAG operators.
class TargetLowering : public TargetLoweringBase {
- TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION;
+ TargetLowering(const TargetLowering&) = delete;
+ void operator=(const TargetLowering&) = delete;
public:
/// NOTE: The TargetMachine owns TLOF.
@@ -2112,8 +2044,7 @@ public:
void AddToWorklist(SDNode *N);
void RemoveFromWorklist(SDNode *N);
- SDValue CombineTo(SDNode *N, const std::vector<SDValue> &To,
- bool AddTo = true);
+ SDValue CombineTo(SDNode *N, ArrayRef<SDValue> To, bool AddTo = true);
SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true);
SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true);
@@ -2252,6 +2183,7 @@ public:
SelectionDAG &DAG;
SDLoc DL;
ImmutableCallSite *CS;
+ bool IsPatchPoint;
SmallVector<ISD::OutputArg, 32> Outs;
SmallVector<SDValue, 32> OutVals;
SmallVector<ISD::InputArg, 32> Ins;
@@ -2260,7 +2192,7 @@ public:
: RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
- DAG(DAG), CS(nullptr) {}
+ DAG(DAG), CS(nullptr), IsPatchPoint(false) {}
CallLoweringInfo &setDebugLoc(SDLoc dl) {
DL = dl;
@@ -2342,6 +2274,11 @@ public:
return *this;
}
+ CallLoweringInfo &setIsPatchPoint(bool Value = true) {
+ IsPatchPoint = Value;
+ return *this;
+ }
+
ArgListTy &getArgs() {
return Args;
}
@@ -2588,7 +2525,8 @@ public:
/// specific constraints and their prefixes, and also tie in the associated
/// operand values. If this returns an empty vector, and if the constraint
/// string itself isn't empty, there was an error parsing.
- virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const;
+ virtual AsmOperandInfoVector ParseConstraints(const TargetRegisterInfo *TRI,
+ ImmutableCallSite CS) const;
/// Examine constraint type and operand type and determine a weight value.
/// The operand object must already have been set up with the operand type.
@@ -2619,10 +2557,10 @@ public:
/// pointer.
///
/// This should only be used for C_Register constraints. On error, this
- /// returns a register number of 0 and a null register class pointer..
- virtual std::pair<unsigned, const TargetRegisterClass*>
- getRegForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const;
+ /// returns a register number of 0 and a null register class pointer.
+ virtual std::pair<unsigned, const TargetRegisterClass *>
+ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+ const std::string &Constraint, MVT VT) const;
/// Try to replace an X constraint, which matches anything, with another that
/// has more specific requirements based on the type of the corresponding
@@ -2652,6 +2590,12 @@ public:
return SDValue();
}
+ /// Indicate whether this target prefers to combine the given number of FDIVs
+ /// with the same divisor.
+ virtual bool combineRepeatedFPDivisors(unsigned NumUsers) const {
+ return false;
+ }
+
/// Hooks for building estimates in place of slower divisions and square
/// roots.
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 7fcb171..57c2606 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -38,13 +38,17 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
const DataLayout *DL;
TargetLoweringObjectFile(
- const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION;
+ const TargetLoweringObjectFile&) = delete;
+ void operator=(const TargetLoweringObjectFile&) = delete;
+
+protected:
+ bool SupportIndirectSymViaGOTPCRel;
public:
MCContext &getContext() const { return *Ctx; }
- TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr) {}
+ TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr),
+ SupportIndirectSymViaGOTPCRel(false) {}
virtual ~TargetLoweringObjectFile();
@@ -94,6 +98,13 @@ public:
return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM);
}
+ virtual const MCSection *
+ getSectionForJumpTable(const Function &F, Mangler &Mang,
+ const TargetMachine &TM) const;
+
+ virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
+ const Function &F) const;
+
/// Targets should implement this method to assign a section to globals with
/// an explicit section specfied. The implementation of this method can
/// assume that GV->hasSection() is true.
@@ -151,11 +162,17 @@ 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;
+ /// \brief Target supports replacing a data "PC"-relative access to a symbol
+ /// through another symbol, by accessing the later via a GOT entry instead?
+ bool supportIndirectSymViaGOTPCRel() const {
+ return SupportIndirectSymViaGOTPCRel;
+ }
+
+ /// \brief Get the target specific PC relative GOT entry relocation
+ virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+ int64_t Offset) const {
+ return nullptr;
+ }
protected:
virtual const MCSection *
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index a4f95c0..cdf643d 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -34,14 +34,14 @@ class Target;
class DataLayout;
class TargetLibraryInfo;
class TargetFrameLowering;
+class TargetIRAnalysis;
class TargetIntrinsicInfo;
class TargetLowering;
class TargetPassConfig;
class TargetRegisterInfo;
class TargetSelectionDAGInfo;
class TargetSubtargetInfo;
-class ScalarTargetTransformInfo;
-class VectorTargetTransformInfo;
+class TargetTransformInfo;
class formatted_raw_ostream;
class raw_ostream;
class TargetLoweringObjectFile;
@@ -59,8 +59,8 @@ using legacy::PassManagerBase;
/// through this interface.
///
class TargetMachine {
- TargetMachine(const TargetMachine &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetMachine &) LLVM_DELETED_FUNCTION;
+ TargetMachine(const TargetMachine &) = delete;
+ void operator=(const TargetMachine &) = delete;
protected: // Can only create subclasses.
TargetMachine(const Target &T, StringRef TargetTriple,
StringRef CPU, StringRef FS, const TargetOptions &Options);
@@ -113,10 +113,16 @@ public:
template<typename STC> const STC &getSubtarget() const {
return *static_cast<const STC*>(getSubtargetImpl());
}
- template <typename STC> const STC &getSubtarget(const Function *) const {
+ template <typename STC> const STC &getSubtarget(const Function &) const {
return *static_cast<const STC*>(getSubtargetImpl());
}
+ /// getDataLayout - This method returns a pointer to the DataLayout for
+ /// the target. It should be unchanging for every subtarget.
+ virtual const DataLayout *getDataLayout() const {
+ return nullptr;
+ }
+
/// \brief Reset the target options based on the function's attributes.
// FIXME: Remove TargetOptions that affect per-function code generation
// from TargetMachine.
@@ -159,31 +165,32 @@ public:
bool shouldPrintMachineCode() const { return Options.PrintMachineCode; }
- /// getAsmVerbosityDefault - Returns the default value of asm verbosity.
+ /// Returns the default value of asm verbosity.
///
- bool getAsmVerbosityDefault() const ;
-
- /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default
- /// is false.
- void setAsmVerbosityDefault(bool);
-
- /// getDataSections - Return true if data objects should be emitted into their
- /// own section, corresponds to -fdata-sections.
- bool getDataSections() const;
+ bool getAsmVerbosityDefault() const {
+ return Options.MCOptions.AsmVerbose;
+ }
- /// getFunctionSections - Return true if functions should be emitted into
- /// their own section, corresponding to -ffunction-sections.
- bool getFunctionSections() const;
+ bool getUniqueSectionNames() const { return Options.UniqueSectionNames; }
- /// setDataSections - Set if the data are emit into separate sections.
- void setDataSections(bool);
+ /// Return true if data objects should be emitted into their own section,
+ /// corresponds to -fdata-sections.
+ bool getDataSections() const {
+ return Options.DataSections;
+ }
- /// setFunctionSections - Set if the functions are emit into separate
- /// sections.
- void setFunctionSections(bool);
+ /// Return true if functions should be emitted into their own section,
+ /// corresponding to -ffunction-sections.
+ bool getFunctionSections() const {
+ return Options.FunctionSections;
+ }
- /// \brief Register analysis passes for this target with a pass manager.
- virtual void addAnalysisPasses(PassManagerBase &) {}
+ /// \brief Get a \c TargetIRAnalysis appropriate for the target.
+ ///
+ /// This is used to construct the new pass manager's target IR analysis pass,
+ /// set up appropriately for this target machine. Even the old pass manager
+ /// uses this to answer queries about the IR.
+ virtual TargetIRAnalysis getTargetIRAnalysis();
/// CodeGenFileType - These enums are meant to be passed into
/// addPassesToEmitFile to indicate what type of file to emit, and returned by
@@ -236,10 +243,11 @@ protected: // Can only create subclasses.
void initAsmInfo();
public:
- /// \brief Register analysis passes for this target with a pass manager.
+ /// \brief Get a TargetIRAnalysis implementation for the target.
///
- /// This registers target independent analysis passes.
- void addAnalysisPasses(PassManagerBase &PM) override;
+ /// This analysis will produce a TTI result which uses the common code
+ /// generator to answer queries about the IR.
+ TargetIRAnalysis getTargetIRAnalysis() override;
/// createPassConfig - Create a pass configuration object to be used by
/// addPassToEmitX methods for generating a pipeline of CodeGen passes.
diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h
index 1fbd2ae..afc2236 100644
--- a/include/llvm/Target/TargetOpcodes.h
+++ b/include/llvm/Target/TargetOpcodes.h
@@ -110,7 +110,18 @@ enum {
/// to prevent the stack guard value or address from being spilled to the
/// stack should override TargetLowering::emitLoadStackGuardNode and
/// additionally expand this pseudo after register allocation.
- LOAD_STACK_GUARD = 19
+ LOAD_STACK_GUARD = 19,
+
+ /// Call instruction with associated vm state for deoptimization and list
+ /// of live pointers for relocation by the garbage collector. It is
+ /// intended to support garbage collection with fully precise relocating
+ /// collectors and deoptimizations in either the callee or caller.
+ STATEPOINT = 20,
+
+ /// Instruction that records the offset of a function's frame allocation in a
+ /// label. Created by the llvm.frameallocate intrinsic. It has two arguments:
+ /// the symbol for the label and the frame index of the stack allocation.
+ FRAME_ALLOC = 21,
};
} // end namespace TargetOpcode
} // end namespace llvm
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index 73014d8..f447fd6 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -78,8 +78,8 @@ namespace llvm {
EnableFastISel(false), PositionIndependentExecutable(false),
UseInitArray(false), DisableIntegratedAS(false),
CompressDebugSections(false), FunctionSections(false),
- DataSections(false), TrapUnreachable(false), TrapFuncName(),
- FloatABIType(FloatABI::Default),
+ DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
+ TrapFuncName(), FloatABIType(FloatABI::Default),
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
FCFI(false), ThreadModel(ThreadModel::POSIX),
CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
@@ -198,6 +198,8 @@ namespace llvm {
/// Emit data into separate sections.
unsigned DataSections : 1;
+ unsigned UniqueSectionNames : 1;
+
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
unsigned TrapUnreachable : 1;
@@ -288,6 +290,12 @@ inline bool operator==(const TargetOptions &LHS,
ARE_EQUAL(TrapFuncName) &&
ARE_EQUAL(FloatABIType) &&
ARE_EQUAL(AllowFPOpFusion) &&
+ ARE_EQUAL(JTType) &&
+ ARE_EQUAL(FCFI) &&
+ ARE_EQUAL(ThreadModel) &&
+ ARE_EQUAL(CFIType) &&
+ ARE_EQUAL(CFIEnforcing) &&
+ ARE_EQUAL(CFIFuncName) &&
ARE_EQUAL(MCOptions);
#undef ARE_EQUAL
}
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 16b72a9..fc94a84 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -45,6 +45,7 @@ public:
const vt_iterator VTs;
const uint32_t *SubClassMask;
const uint16_t *SuperRegIndices;
+ const unsigned LaneMask;
const sc_iterator SuperClasses;
ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&);
@@ -190,6 +191,13 @@ public:
ArrayRef<MCPhysReg> getRawAllocationOrder(const MachineFunction &MF) const {
return OrderFunc ? OrderFunc(MF) : makeArrayRef(begin(), getNumRegs());
}
+
+ /// Returns the combination of all lane masks of register in this class.
+ /// The lane masks of the registers are the combination of all lane masks
+ /// of their subregisters.
+ unsigned getLaneMask() const {
+ return LaneMask;
+ }
};
/// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about
@@ -448,6 +456,11 @@ public:
/// used by register scavenger to determine what registers are free.
virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0;
+ /// Prior to adding the live-out mask to a stackmap or patchpoint
+ /// instruction, provide the target the opportunity to adjust it (mainly to
+ /// remove pseudo-registers that should be ignored).
+ virtual void adjustStackMapLiveOutMask(uint32_t *Mask) const { }
+
/// getMatchingSuperReg - Return a super-register of the specified register
/// Reg so its sub-register of index SubIdx is Reg.
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
@@ -502,6 +515,15 @@ public:
return composeSubRegIndicesImpl(a, b);
}
+ /// Transforms a LaneMask computed for one subregister to the lanemask that
+ /// would have been computed when composing the subsubregisters with IdxA
+ /// first. @sa composeSubRegIndices()
+ unsigned composeSubRegIndexLaneMask(unsigned IdxA, unsigned LaneMask) const {
+ if (!IdxA)
+ return LaneMask;
+ return composeSubRegIndexLaneMaskImpl(IdxA, LaneMask);
+ }
+
/// Debugging helper: dump register in human readable form to dbgs() stream.
static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0,
const TargetRegisterInfo* TRI = nullptr);
@@ -512,6 +534,12 @@ protected:
llvm_unreachable("Target has no sub-registers");
}
+ /// Overridden by TableGen in targets that have sub-registers.
+ virtual unsigned
+ composeSubRegIndexLaneMaskImpl(unsigned, unsigned) const {
+ llvm_unreachable("Target has no sub-registers");
+ }
+
public:
/// getCommonSuperRegClass - Find a common super-register class if it exists.
///
@@ -666,13 +694,13 @@ public:
return false;
}
- /// UpdateRegAllocHint - A callback to allow target a chance to update
+ /// updateRegAllocHint - A callback to allow target a chance to update
/// register allocation hints when a register is "changed" (e.g. coalesced)
/// to another register. e.g. On ARM, some virtual registers should target
/// register pairs, if one of pair is coalesced to another register, the
/// allocation hint of the other half of the pair should be changed to point
/// to the new register.
- virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
+ virtual void updateRegAllocHint(unsigned Reg, unsigned NewReg,
MachineFunction &MF) const {
// Do nothing.
}
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index f63afd7..d297162 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -188,6 +188,22 @@ def SDTIStore : SDTypeProfile<1, 3, [ // indexed store
SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3>
]>;
+def SDTMaskedStore: SDTypeProfile<0, 3, [ // masked store
+ SDTCisPtrTy<0>, SDTCisVec<1>, SDTCisVec<2>
+]>;
+
+def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load
+ SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>
+]>;
+
+def SDTMaskedGather: SDTypeProfile<1, 3, [ // masked gather
+ SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisVec<2>
+]>;
+
+def SDTMaskedScatter: SDTypeProfile<1, 3, [ // masked scatter
+ SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>
+]>;
+
def SDTVecShuffle : SDTypeProfile<1, 2, [
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>
]>;
@@ -363,6 +379,7 @@ def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>;
def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>;
def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>;
def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>;
+def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>;
def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>;
def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>;
@@ -372,6 +389,7 @@ def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>;
def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>;
def frem : SDNode<"ISD::FREM" , SDTFPBinOp>;
def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>;
+def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>;
def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>;
def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>;
def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>;
@@ -454,6 +472,15 @@ def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad,
def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore,
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad,
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+def masked_scatter : SDNode<"ISD::MSCATTER", SDTMaskedScatter,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather,
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+
// Do not use ld, st directly. Use load, extload, sextload, zextload, store,
// and truncst (see below).
def ld : SDNode<"ISD::LOAD" , SDTLoad,
diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h
index d1a3fcf..bacdd95 100644
--- a/include/llvm/Target/TargetSelectionDAGInfo.h
+++ b/include/llvm/Target/TargetSelectionDAGInfo.h
@@ -21,15 +21,14 @@
namespace llvm {
class DataLayout;
-class TargetMachine;
//===----------------------------------------------------------------------===//
/// TargetSelectionDAGInfo - Targets can subclass this to parameterize the
/// SelectionDAG lowering and instruction selection process.
///
class TargetSelectionDAGInfo {
- TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION;
- void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION;
+ TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete;
+ void operator=(const TargetSelectionDAGInfo &) = delete;
const DataLayout *DL;
diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h
index 80ff9e3..83ab4ec 100644
--- a/include/llvm/Target/TargetSubtargetInfo.h
+++ b/include/llvm/Target/TargetSubtargetInfo.h
@@ -42,8 +42,8 @@ template <typename T> class SmallVectorImpl;
/// be exposed through a TargetSubtargetInfo-derived class.
///
class TargetSubtargetInfo : public MCSubtargetInfo {
- TargetSubtargetInfo(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION;
- void operator=(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION;
+ TargetSubtargetInfo(const TargetSubtargetInfo&) = delete;
+ void operator=(const TargetSubtargetInfo&) = delete;
protected: // Can only create subclasses...
TargetSubtargetInfo();
public:
@@ -71,7 +71,6 @@ public:
virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const {
return nullptr;
}
- virtual const DataLayout *getDataLayout() const { return nullptr; }
/// getRegisterInfo - If register information is available, return it. If
/// not, return null. This is kept separate from RegInfo until RegInfo has
@@ -168,6 +167,11 @@ public:
virtual std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const {
return nullptr;
}
+
+ /// Enable tracking of subregister liveness in register allocator.
+ virtual bool enableSubRegLiveness() const {
+ return false;
+ }
};
} // End llvm namespace
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index ce1a7d6..fbd999c 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -199,6 +199,10 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
+/// \brief This pass lowers bitset metadata and the llvm.bitset.test intrinsic
+/// to bitsets.
+ModulePass *createLowerBitSetsPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/IPO/LowerBitSets.h b/include/llvm/Transforms/IPO/LowerBitSets.h
new file mode 100644
index 0000000..0f60617
--- /dev/null
+++ b/include/llvm/Transforms/IPO/LowerBitSets.h
@@ -0,0 +1,153 @@
+//===- LowerBitSets.h - Bitset lowering pass --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines parts of the bitset lowering pass implementation that may
+// be usefully unit tested.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
+#define LLVM_TRANSFORMS_IPO_LOWERBITSETS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <stdint.h>
+#include <limits>
+#include <set>
+#include <vector>
+
+namespace llvm {
+
+class DataLayout;
+class GlobalVariable;
+class Value;
+
+struct BitSetInfo {
+ // The actual bitset.
+ std::vector<uint8_t> Bits;
+
+ // The byte offset into the combined global represented by the bitset.
+ uint64_t ByteOffset;
+
+ // The size of the bitset in bits.
+ uint64_t BitSize;
+
+ // Log2 alignment of the bit set relative to the combined global.
+ // For example, a log2 alignment of 3 means that bits in the bitset
+ // represent addresses 8 bytes apart.
+ unsigned AlignLog2;
+
+ bool isSingleOffset() const {
+ return Bits.size() == 1 && Bits[0] == 1;
+ }
+
+ bool isAllOnes() const {
+ for (unsigned I = 0; I != Bits.size() - 1; ++I)
+ if (Bits[I] != 0xFF)
+ return false;
+
+ if (BitSize % 8 == 0)
+ return Bits[Bits.size() - 1] == 0xFF;
+
+ return Bits[Bits.size() - 1] == (1 << (BitSize % 8)) - 1;
+ }
+
+ bool containsGlobalOffset(uint64_t Offset) const;
+
+ bool containsValue(const DataLayout *DL,
+ const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout,
+ Value *V, uint64_t COffset = 0) const;
+
+};
+
+struct BitSetBuilder {
+ SmallVector<uint64_t, 16> Offsets;
+ uint64_t Min, Max;
+
+ BitSetBuilder() : Min(std::numeric_limits<uint64_t>::max()), Max(0) {}
+
+ void addOffset(uint64_t Offset) {
+ if (Min > Offset)
+ Min = Offset;
+ if (Max < Offset)
+ Max = Offset;
+
+ Offsets.push_back(Offset);
+ }
+
+ BitSetInfo build();
+};
+
+/// This class implements a layout algorithm for globals referenced by bit sets
+/// that tries to keep members of small bit sets together. This can
+/// significantly reduce bit set sizes in many cases.
+///
+/// It works by assembling fragments of layout from sets of referenced globals.
+/// Each set of referenced globals causes the algorithm to create a new
+/// fragment, which is assembled by appending each referenced global in the set
+/// into the fragment. If a referenced global has already been referenced by an
+/// fragment created earlier, we instead delete that fragment and append its
+/// contents into the fragment we are assembling.
+///
+/// By starting with the smallest fragments, we minimize the size of the
+/// fragments that are copied into larger fragments. This is most intuitively
+/// thought about when considering the case where the globals are virtual tables
+/// and the bit sets represent their derived classes: in a single inheritance
+/// hierarchy, the optimum layout would involve a depth-first search of the
+/// class hierarchy (and in fact the computed layout ends up looking a lot like
+/// a DFS), but a naive DFS would not work well in the presence of multiple
+/// inheritance. This aspect of the algorithm ends up fitting smaller
+/// hierarchies inside larger ones where that would be beneficial.
+///
+/// For example, consider this class hierarchy:
+///
+/// A B
+/// \ / | \
+/// C D E
+///
+/// We have five bit sets: bsA (A, C), bsB (B, C, D, E), bsC (C), bsD (D) and
+/// bsE (E). If we laid out our objects by DFS traversing B followed by A, our
+/// layout would be {B, C, D, E, A}. This is optimal for bsB as it needs to
+/// cover the only 4 objects in its hierarchy, but not for bsA as it needs to
+/// cover 5 objects, i.e. the entire layout. Our algorithm proceeds as follows:
+///
+/// Add bsC, fragments {{C}}
+/// Add bsD, fragments {{C}, {D}}
+/// Add bsE, fragments {{C}, {D}, {E}}
+/// Add bsA, fragments {{A, C}, {D}, {E}}
+/// Add bsB, fragments {{B, A, C, D, E}}
+///
+/// This layout is optimal for bsA, as it now only needs to cover two (i.e. 3
+/// fewer) objects, at the cost of bsB needing to cover 1 more object.
+///
+/// The bit set lowering pass assigns an object index to each object that needs
+/// to be laid out, and calls addFragment for each bit set passing the object
+/// indices of its referenced globals. It then assembles a layout from the
+/// computed layout in the Fragments field.
+struct GlobalLayoutBuilder {
+ /// The computed layout. Each element of this vector contains a fragment of
+ /// layout (which may be empty) consisting of object indices.
+ std::vector<std::vector<uint64_t>> Fragments;
+
+ /// Mapping from object index to fragment index.
+ std::vector<uint64_t> FragmentMap;
+
+ GlobalLayoutBuilder(uint64_t NumObjects)
+ : Fragments(1), FragmentMap(NumObjects) {}
+
+ /// Add F to the layout while trying to keep its indices contiguous.
+ /// If a previously seen fragment uses any of F's indices, that
+ /// fragment will be laid out inside F.
+ void addFragment(const std::set<uint64_t> &F);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index b1426b4..65f4712 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -19,7 +19,7 @@
namespace llvm {
class Pass;
-class TargetLibraryInfo;
+class TargetLibraryInfoImpl;
class TargetMachine;
// The old pass manager infrastructure is hidden in a legacy namespace now.
@@ -27,8 +27,6 @@ namespace legacy {
class FunctionPassManager;
class PassManagerBase;
}
-using legacy::FunctionPassManager;
-using legacy::PassManagerBase;
/// PassManagerBuilder - This class is used to set up a standard optimization
/// sequence for languages like C and C++, allowing some APIs to customize the
@@ -59,7 +57,7 @@ public:
/// Extensions are passed the builder itself (so they can see how it is
/// configured) as well as the pass manager to add stuff to.
typedef void (*ExtensionFn)(const PassManagerBuilder &Builder,
- PassManagerBase &PM);
+ legacy::PassManagerBase &PM);
enum ExtensionPointTy {
/// EP_EarlyAsPossible - This extension point allows adding passes before
/// any other transformations, allowing them to see the code as it is coming
@@ -105,7 +103,7 @@ public:
/// LibraryInfo - Specifies information about the runtime library for the
/// optimizer. If this is non-null, it is added to both the function and
/// per-module pass pipeline.
- TargetLibraryInfo *LibraryInfo;
+ TargetLibraryInfoImpl *LibraryInfo;
/// Inliner - Specifies the inliner to use. If this is non-null, it is
/// added to the per-module passes.
@@ -139,19 +137,20 @@ public:
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn);
private:
- void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const;
- void addInitialAliasAnalysisPasses(PassManagerBase &PM) const;
- void addLTOOptimizationPasses(PassManagerBase &PM);
+ void addExtensionsToPM(ExtensionPointTy ETy,
+ legacy::PassManagerBase &PM) const;
+ void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const;
+ void addLTOOptimizationPasses(legacy::PassManagerBase &PM);
public:
/// populateFunctionPassManager - This fills in the function pass manager,
/// which is expected to be run on each function immediately as it is
/// generated. The idea is to reduce the size of the IR in memory.
- void populateFunctionPassManager(FunctionPassManager &FPM);
+ void populateFunctionPassManager(legacy::FunctionPassManager &FPM);
/// populateModulePassManager - This sets up the primary pass manager.
- void populateModulePassManager(PassManagerBase &MPM);
- void populateLTOPassManager(PassManagerBase &PM, TargetMachine *TM = nullptr);
+ void populateModulePassManager(legacy::PassManagerBase &MPM);
+ void populateLTOPassManager(legacy::PassManagerBase &PM);
};
/// Registers a function for adding a standard set of passes. This should be
diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h
new file mode 100644
index 0000000..f48ec13
--- /dev/null
+++ b/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -0,0 +1,46 @@
+//===- InstCombine.h - InstCombine pass -------------------------*- 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 the primary interface to the instcombine pass. This pass
+/// is suitable for use in the new pass manager. For a pass that works with the
+/// legacy pass manager, please look for \c createInstructionCombiningPass() in
+/// Scalar.h.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
+#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/InstCombine/InstCombineWorklist.h"
+
+namespace llvm {
+
+class InstCombinePass {
+ InstCombineWorklist Worklist;
+
+public:
+ static StringRef name() { return "InstCombinePass"; }
+
+ // Explicitly define constructors for MSVC.
+ InstCombinePass() {}
+ InstCombinePass(InstCombinePass &&Arg) : Worklist(std::move(Arg.Worklist)) {}
+ InstCombinePass &operator=(InstCombinePass &&RHS) {
+ Worklist = std::move(RHS.Worklist);
+ return *this;
+ }
+
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
new file mode 100644
index 0000000..a6bad34
--- /dev/null
+++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h
@@ -0,0 +1,116 @@
+//===- InstCombineWorklist.h - Worklist for InstCombine pass ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H
+#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "instcombine"
+
+namespace llvm {
+
+/// InstCombineWorklist - This is the worklist management logic for
+/// InstCombine.
+class InstCombineWorklist {
+ SmallVector<Instruction*, 256> Worklist;
+ DenseMap<Instruction*, unsigned> WorklistMap;
+
+ void operator=(const InstCombineWorklist&RHS) = delete;
+ InstCombineWorklist(const InstCombineWorklist&) = delete;
+public:
+ InstCombineWorklist() {}
+
+ InstCombineWorklist(InstCombineWorklist &&Arg)
+ : Worklist(std::move(Arg.Worklist)),
+ WorklistMap(std::move(Arg.WorklistMap)) {}
+ InstCombineWorklist &operator=(InstCombineWorklist &&RHS) {
+ Worklist = std::move(RHS.Worklist);
+ WorklistMap = std::move(RHS.WorklistMap);
+ return *this;
+ }
+
+ bool isEmpty() const { return Worklist.empty(); }
+
+ /// Add - Add the specified instruction to the worklist if it isn't already
+ /// in it.
+ void Add(Instruction *I) {
+ if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) {
+ DEBUG(dbgs() << "IC: ADD: " << *I << '\n');
+ Worklist.push_back(I);
+ }
+ }
+
+ void AddValue(Value *V) {
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ Add(I);
+ }
+
+ /// AddInitialGroup - Add the specified batch of stuff in reverse order.
+ /// which should only be done when the worklist is empty and when the group
+ /// has no duplicates.
+ void AddInitialGroup(Instruction *const *List, unsigned NumEntries) {
+ assert(Worklist.empty() && "Worklist must be empty to add initial group");
+ Worklist.reserve(NumEntries+16);
+ WorklistMap.resize(NumEntries);
+ DEBUG(dbgs() << "IC: ADDING: " << NumEntries << " instrs to worklist\n");
+ for (unsigned Idx = 0; NumEntries; --NumEntries) {
+ Instruction *I = List[NumEntries-1];
+ WorklistMap.insert(std::make_pair(I, Idx++));
+ Worklist.push_back(I);
+ }
+ }
+
+ // Remove - remove I from the worklist if it exists.
+ void Remove(Instruction *I) {
+ DenseMap<Instruction*, unsigned>::iterator It = WorklistMap.find(I);
+ if (It == WorklistMap.end()) return; // Not in worklist.
+
+ // Don't bother moving everything down, just null out the slot.
+ Worklist[It->second] = nullptr;
+
+ WorklistMap.erase(It);
+ }
+
+ Instruction *RemoveOne() {
+ Instruction *I = Worklist.pop_back_val();
+ WorklistMap.erase(I);
+ return I;
+ }
+
+ /// AddUsersToWorkList - When an instruction is simplified, add all users of
+ /// the instruction to the work lists because they might get more simplified
+ /// now.
+ ///
+ void AddUsersToWorkList(Instruction &I) {
+ for (User *U : I.users())
+ Add(cast<Instruction>(U));
+ }
+
+
+ /// Zap - check that the worklist is empty and nuke the backing store for
+ /// the map if it is large.
+ void Zap() {
+ assert(WorklistMap.empty() && "Worklist empty, but map not?");
+
+ // Do an explicit clear, this shrinks the map if needed.
+ WorklistMap.clear();
+ }
+};
+
+} // end namespace llvm.
+
+#undef DEBUG_TYPE
+
+#endif
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 87422df..8fac6ca 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -15,6 +15,7 @@
#define LLVM_TRANSFORMS_INSTRUMENTATION_H
#include "llvm/ADT/StringRef.h"
+#include <vector>
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
inline void *getDFSanArgTLSPtrForJIT() {
@@ -63,6 +64,18 @@ struct GCOVOptions {
ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
+/// Options for the frontend instrumentation based profiling pass.
+struct InstrProfOptions {
+ InstrProfOptions() : NoRedZone(false) {}
+
+ // Add the 'noredzone' attribute to added runtime library calls.
+ bool NoRedZone;
+};
+
+/// Insert frontend instrumentation based profiling.
+ModulePass *createInstrProfilingPass(
+ const InstrProfOptions &Options = InstrProfOptions());
+
// Insert AddressSanitizer (address sanity checking) instrumentation
FunctionPass *createAddressSanitizerFunctionPass();
ModulePass *createAddressSanitizerModulePass();
@@ -74,17 +87,17 @@ FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0);
FunctionPass *createThreadSanitizerPass();
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
-ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(),
- void *(*getArgTLS)() = nullptr,
- void *(*getRetValTLS)() = nullptr);
+ModulePass *createDataFlowSanitizerPass(
+ const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
+ void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr);
// Insert SanitizerCoverage instrumentation.
ModulePass *createSanitizerCoverageModulePass(int CoverageLevel);
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
-inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
- StringRef()) {
- return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT,
+inline ModulePass *createDataFlowSanitizerPassForJIT(
+ const std::vector<std::string> &ABIListFiles = std::vector<std::string>()) {
+ return createDataFlowSanitizerPass(ABIListFiles, getDFSanArgTLSPtrForJIT,
getDFSanRetValTLSPtrForJIT);
}
#endif
@@ -93,37 +106,6 @@ inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile =
// checking on loads, stores, and other memory intrinsics.
FunctionPass *createBoundsCheckingPass();
-/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB (or
-/// GDB) and generate a file with the LLVM IR to be
-/// displayed in the debugger.
-///
-/// Existing debug metadata is preserved (but may be modified) in order to allow
-/// accessing variables in the original source. The line table and file
-/// information is modified to correspond to the lines in the LLVM IR. If
-/// Filename and Directory are empty, a file name is generated based on existing
-/// debug information. If no debug information is available, a temporary file
-/// name is generated.
-///
-/// @param HideDebugIntrinsics Omit debug intrinsics in emitted IR source file.
-/// @param HideDebugMetadata Omit debug metadata in emitted IR source file.
-/// @param Directory Embed this directory in the debug information.
-/// @param Filename Embed this file name in the debug information.
-ModulePass *createDebugIRPass(bool HideDebugIntrinsics,
- bool HideDebugMetadata,
- StringRef Directory = StringRef(),
- StringRef Filename = StringRef());
-
-/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB
-/// (or GDB) with an existing IR file on disk. When creating
-/// a DebugIR pass with this function, no source file is
-/// output to disk and the existing one is unmodified. Debug
-/// metadata in the Module is created/updated to point to
-/// the existing textual IR file on disk.
-/// NOTE: If the IR file to be debugged is not on disk, use the version of this
-/// function with parameters in order to generate the file that will be
-/// seen by the debugger.
-ModulePass *createDebugIRPass();
-
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 5dcd899..558b81e 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -21,6 +21,7 @@ namespace llvm {
class BasicBlockPass;
class FunctionPass;
+class ModulePass;
class Pass;
class GetElementPtrInst;
class PassInfo;
@@ -81,6 +82,13 @@ FunctionPass *createAggressiveDCEPass();
//===----------------------------------------------------------------------===//
//
+// BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to
+// remove computations of dead bits.
+//
+FunctionPass *createBitTrackingDCEPass();
+
+//===----------------------------------------------------------------------===//
+//
// SROA - Replace aggregates or pieces of aggregates with scalar SSA values.
//
FunctionPass *createSROAPass(bool RequiresDomTree = true);
@@ -98,6 +106,13 @@ FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1,
//===----------------------------------------------------------------------===//
//
+// InductiveRangeCheckElimination - Transform loops to elide range checks on
+// linear functions of the induction variable.
+//
+Pass *createInductiveRangeCheckEliminationPass();
+
+//===----------------------------------------------------------------------===//
+//
// InductionVariableSimplify - Transform induction variables in a program to all
// use a single canonical induction variable per loop.
//
@@ -130,7 +145,7 @@ Pass *createLICMPass();
//
Pass *createLoopStrengthReducePass();
-Pass *createGlobalMergePass(const TargetMachine *TM = nullptr);
+Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset);
//===----------------------------------------------------------------------===//
//
@@ -405,6 +420,26 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
//
BasicBlockPass *createLoadCombinePass();
+FunctionPass *createStraightLineStrengthReducePass();
+
+
+//===----------------------------------------------------------------------===//
+//
+// PlaceSafepoints - Rewrite any IR calls to gc.statepoints and insert any
+// safepoint polls (method entry, backedge) that might be required. This pass
+// does not generate explicit relocation sequences - that's handled by
+// RewriteStatepointsForGC which can be run at an arbitrary point in the pass
+// order following this pass.
+//
+ModulePass *createPlaceSafepointsPass();
+
+//===----------------------------------------------------------------------===//
+//
+// RewriteStatepointsForGC - Rewrite any gc.statepoints which do not yet have
+// explicit relocations to include explicit relocations.
+//
+FunctionPass *createRewriteStatepointsForGCPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar/EarlyCSE.h b/include/llvm/Transforms/Scalar/EarlyCSE.h
new file mode 100644
index 0000000..e3dd3c0
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/EarlyCSE.h
@@ -0,0 +1,39 @@
+//===- EarlyCSE.h - Simple and fast CSE pass --------------------*- 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 the interface for a simple, fast CSE pass.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_EARLYCSE_H
+#define LLVM_TRANSFORMS_SCALAR_EARLYCSE_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// \brief A simple and fast domtree-based CSE pass.
+///
+/// This pass does a simple depth-first walk over the dominator tree,
+/// eliminating trivially redundant instructions and using instsimplify to
+/// canonicalize things as it goes. It is intended to be fast and catch obvious
+/// cases so that instcombine and other passes are more effective. It is
+/// expected that a later pass of GVN will catch the interesting/hard cases.
+class EarlyCSEPass {
+public:
+ static StringRef name() { return "EarlyCSEPass"; }
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
new file mode 100644
index 0000000..4028320
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h
@@ -0,0 +1,40 @@
+//===- LowerExpectIntrinsic.h - LowerExpectIntrinsic pass -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// The header file for the LowerExpectIntrinsic pass as used by the new pass
+/// manager.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H
+#define LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class LowerExpectIntrinsicPass {
+public:
+ static StringRef name() { return "LowerExpectIntrinsicPass"; }
+
+ /// \brief Run the pass over the function.
+ ///
+ /// This will lower all of th expect intrinsic calls in this function into
+ /// branch weight metadata. That metadata will subsequently feed the analysis
+ /// of the probabilities and frequencies of the CFG. After running this pass,
+ /// no more expect intrinsics remain, allowing the rest of the optimizer to
+ /// ignore them.
+ PreservedAnalyses run(Function &F);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h
new file mode 100644
index 0000000..ef28e0f
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h
@@ -0,0 +1,46 @@
+//===- SimplifyCFG.h - Simplify and canonicalize the CFG --------*- 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 the interface for the pass responsible for both
+/// simplifying and canonicalizing the CFG.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
+#define LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// \brief A pass to simplify and canonicalize the CFG of a function.
+///
+/// This pass iteratively simplifies the entire CFG of a function, removing
+/// unnecessary control flows and bringing it into the canonical form expected
+/// by the rest of the mid-level optimizer.
+class SimplifyCFGPass {
+ int BonusInstThreshold;
+
+public:
+ static StringRef name() { return "SimplifyCFGPass"; }
+
+ /// \brief Construct a pass with the default thresholds.
+ SimplifyCFGPass();
+
+ /// \brief Construct a pass with a specific bonus threshold.
+ SimplifyCFGPass(int BonusInstThreshold);
+
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 19acf5b..710db03 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -23,10 +23,11 @@
namespace llvm {
class AliasAnalysis;
+class MemoryDependenceAnalysis;
class DominatorTree;
+class LoopInfo;
class Instruction;
class MDNode;
-class Pass;
class ReturnInst;
class TargetLibraryInfo;
class TerminatorInst;
@@ -39,7 +40,8 @@ void DeleteDeadBlock(BasicBlock *BB);
/// any single-entry PHI nodes in it, fold them away. This handles the case
/// when all entries to the PHI nodes in a block are guaranteed equal, such as
/// when the block has exactly one predecessor.
-void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = nullptr);
+void FoldSingleEntryPHINodes(BasicBlock *BB, AliasAnalysis *AA = nullptr,
+ MemoryDependenceAnalysis *MemDep = nullptr);
/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it
/// is dead. Also recursively delete any operands that become dead as
@@ -50,7 +52,10 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr);
/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor,
/// if possible. The return value indicates success or failure.
-bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = nullptr);
+bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ AliasAnalysis *AA = nullptr,
+ MemoryDependenceAnalysis *MemDep = nullptr);
// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI)
// with a value, then remove and delete the original instruction.
@@ -70,18 +75,62 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL,
//
void ReplaceInstWithInst(Instruction *From, Instruction *To);
+/// \brief Option class for critical edge splitting.
+///
+/// This provides a builder interface for overriding the default options used
+/// during critical edge splitting.
+struct CriticalEdgeSplittingOptions {
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+ LoopInfo *LI;
+ bool MergeIdenticalEdges;
+ bool DontDeleteUselessPHIs;
+ bool PreserveLCSSA;
+
+ CriticalEdgeSplittingOptions()
+ : AA(nullptr), DT(nullptr), LI(nullptr), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ /// \brief Basic case of setting up all the analysis.
+ CriticalEdgeSplittingOptions(AliasAnalysis *AA, DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr)
+ : AA(AA), DT(DT), LI(LI), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ /// \brief A common pattern is to preserve the dominator tree and loop
+ /// info but not care about AA.
+ CriticalEdgeSplittingOptions(DominatorTree *DT, LoopInfo *LI)
+ : AA(nullptr), DT(DT), LI(LI), MergeIdenticalEdges(false),
+ DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+
+ CriticalEdgeSplittingOptions &setMergeIdenticalEdges() {
+ MergeIdenticalEdges = true;
+ return *this;
+ }
+
+ CriticalEdgeSplittingOptions &setDontDeleteUselessPHIs() {
+ DontDeleteUselessPHIs = true;
+ return *this;
+ }
+
+ CriticalEdgeSplittingOptions &setPreserveLCSSA() {
+ PreserveLCSSA = true;
+ return *this;
+ }
+};
+
/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
-/// split the critical edge. This will update DominatorTree and
-/// DominatorFrontier information if it is available, thus calling this pass
-/// will not invalidate either of them. This returns the new block if the edge
-/// was split, null otherwise.
+/// split the critical edge. This will update the analyses passed in through
+/// the option struct. This returns the new block if the edge was split, null
+/// otherwise.
///
-/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the
-/// specified successor will be merged into the same critical edge block.
-/// This is most commonly interesting with switch instructions, which may
-/// have many edges to any one destination. This ensures that all edges to that
-/// dest go to one block instead of each going to a different block, but isn't
-/// the standard definition of a "critical edge".
+/// If MergeIdenticalEdges in the options struct is true (not the default),
+/// *all* edges from TI to the specified successor will be merged into the same
+/// critical edge block. This is most commonly interesting with switch
+/// instructions, which may have many edges to any one destination. This
+/// ensures that all edges to that dest go to one block instead of each going
+/// to a different block, but isn't the standard definition of a "critical
+/// edge".
///
/// It is invalid to call this function on a critical edge that starts at an
/// IndirectBrInst. Splitting these edges will almost always create an invalid
@@ -89,14 +138,15 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To);
/// to.
///
BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
- Pass *P = nullptr,
- bool MergeIdenticalEdges = false,
- bool DontDeleteUselessPHIs = false,
- bool SplitLandingPads = false);
-
-inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
- Pass *P = nullptr) {
- return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P);
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions());
+
+inline BasicBlock *
+SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
+ return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(),
+ Options);
}
/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return
@@ -105,55 +155,62 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
/// function. If P is specified, it updates the analyses
/// described above.
inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI,
- Pass *P = nullptr) {
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
bool MadeChange = false;
TerminatorInst *TI = (*PI)->getTerminator();
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
if (TI->getSuccessor(i) == Succ)
- MadeChange |= !!SplitCriticalEdge(TI, i, P);
+ MadeChange |= !!SplitCriticalEdge(TI, i, Options);
return MadeChange;
}
/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge
/// and return true, otherwise return false. This method requires that there be
-/// an edge between the two blocks. If P is specified, it updates the analyses
-/// described above.
-inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
- Pass *P = nullptr,
- bool MergeIdenticalEdges = false,
- bool DontDeleteUselessPHIs = false) {
+/// an edge between the two blocks. It updates the analyses
+/// passed in the options struct
+inline BasicBlock *
+SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions()) {
TerminatorInst *TI = Src->getTerminator();
unsigned i = 0;
while (1) {
assert(i != TI->getNumSuccessors() && "Edge doesn't exist!");
if (TI->getSuccessor(i) == Dst)
- return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges,
- DontDeleteUselessPHIs);
+ return SplitCriticalEdge(TI, i, Options);
++i;
}
}
// SplitAllCriticalEdges - Loop over all of the edges in the CFG,
-// breaking critical edges as they are found. Pass P must not be NULL.
+// breaking critical edges as they are found.
// Returns the number of broken edges.
-unsigned SplitAllCriticalEdges(Function &F, Pass *P);
+unsigned SplitAllCriticalEdges(Function &F,
+ const CriticalEdgeSplittingOptions &Options =
+ CriticalEdgeSplittingOptions());
-/// SplitEdge - Split the edge connecting specified block. Pass P must
-/// not be NULL.
-BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P);
+/// SplitEdge - Split the edge connecting specified block.
+BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
+ DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
/// SplitBlock - Split the specified block at the specified instruction - every
/// thing before SplitPt stays in Old and everything starting with SplitPt moves
/// to a new block. The two blocks are joined by an unconditional branch and
/// the loop info is updated.
///
-BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P);
+BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt,
+ DominatorTree *DT = nullptr, LoopInfo *LI = nullptr);
-/// SplitBlockPredecessors - This method transforms BB by introducing a new
-/// basic block into the function, and moving some of the predecessors of BB to
-/// be predecessors of the new block. The new predecessors are indicated by the
-/// Preds array, which has NumPreds elements in it. The new block is given a
-/// suffix of 'Suffix'. This function returns the new block.
+/// SplitBlockPredecessors - This method introduces at least one new basic block
+/// into the function and moves some of the predecessors of BB to be
+/// predecessors of the new block. The new predecessors are indicated by the
+/// Preds array. The new block is given a suffix of 'Suffix'. Returns new basic
+/// block to which predecessors from Preds are now pointing.
+///
+/// If BB is a landingpad block then additional basicblock might be introduced.
+/// It will have Suffix+".split_lp". See SplitLandingPadPredecessors for more
+/// details on this case.
///
/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses.
@@ -161,8 +218,12 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P);
/// complicated to handle the case where one of the edges being split
/// is an exit of a loop with other exits).
///
-BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds,
- const char *Suffix, Pass *P = nullptr);
+BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
+ const char *Suffix,
+ AliasAnalysis *AA = nullptr,
+ DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ bool PreserveLCSSA = false);
/// SplitLandingPadPredecessors - This method transforms the landing pad,
/// OrigBB, by introducing two new basic blocks into the function. One of those
@@ -177,9 +238,14 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds,
/// case where one of the edges being split is an exit of a loop with other
/// exits).
///
-void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef<BasicBlock*> Preds,
+void SplitLandingPadPredecessors(BasicBlock *OrigBB,
+ ArrayRef<BasicBlock *> Preds,
const char *Suffix, const char *Suffix2,
- Pass *P, SmallVectorImpl<BasicBlock*> &NewBBs);
+ SmallVectorImpl<BasicBlock *> &NewBBs,
+ AliasAnalysis *AA = nullptr,
+ DominatorTree *DT = nullptr,
+ LoopInfo *LI = nullptr,
+ bool PreserveLCSSA = false);
/// FoldReturnIntoUncondBranch - This method duplicates the specified return
/// instruction into a predecessor which ends in an unconditional branch. If
diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h
index 1e407fb..6387c16 100644
--- a/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -115,20 +115,6 @@ namespace llvm {
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
const DataLayout *TD, const TargetLibraryInfo *TLI);
-
- /// SimplifyFortifiedLibCalls - Helper class for folding checked library
- /// calls (e.g. __strcpy_chk) into their unchecked counterparts.
- class SimplifyFortifiedLibCalls {
- protected:
- CallInst *CI;
- virtual void replaceCall(Value *With) = 0;
- virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp,
- bool isString) const = 0;
-
- public:
- virtual ~SimplifyFortifiedLibCalls();
- bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI);
- };
}
#endif
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 740d725..d1563ef 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -44,7 +44,7 @@ class Loop;
class LoopInfo;
class AllocaInst;
class AliasAnalysis;
-class AssumptionTracker;
+class AssumptionCacheTracker;
/// CloneModule - Return an exact copy of the specified module
///
@@ -95,8 +95,7 @@ struct ClonedCodeInfo {
/// function, you can specify a ClonedCodeInfo object with the optional fifth
/// parameter.
///
-BasicBlock *CloneBasicBlock(const BasicBlock *BB,
- ValueToValueMapTy &VMap,
+BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
const Twine &NameSuffix = "", Function *F = nullptr,
ClonedCodeInfo *CodeInfo = nullptr);
@@ -112,8 +111,7 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB,
/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue
/// mappings, and debug info metadata will not be cloned.
///
-Function *CloneFunction(const Function *F,
- ValueToValueMapTy &VMap,
+Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap,
bool ModuleLevelChanges,
ClonedCodeInfo *CodeInfo = nullptr);
@@ -127,14 +125,49 @@ Function *CloneFunction(const Function *F,
/// mappings.
///
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
- ValueToValueMapTy &VMap,
- bool ModuleLevelChanges,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix = "",
ClonedCodeInfo *CodeInfo = nullptr,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+/// A helper class used with CloneAndPruneIntoFromInst to change the default
+/// behavior while instructions are being cloned.
+class CloningDirector {
+public:
+ /// This enumeration describes the way CloneAndPruneIntoFromInst should
+ /// proceed after the CloningDirector has examined an instruction.
+ enum CloningAction {
+ ///< Continue cloning the instruction (default behavior).
+ CloneInstruction,
+ ///< Skip this instruction but continue cloning the current basic block.
+ SkipInstruction,
+ ///< Skip this instruction and stop cloning the current basic block.
+ StopCloningBB
+ };
+
+ virtual ~CloningDirector() {}
+
+ /// Subclasses must override this function to customize cloning behavior.
+ virtual CloningAction handleInstruction(ValueToValueMapTy &VMap,
+ const Instruction *Inst,
+ BasicBlock *NewBB) = 0;
+
+ virtual ValueMapTypeRemapper *getTypeRemapper() { return nullptr; }
+ virtual ValueMaterializer *getValueMaterializer() { return nullptr; }
+};
+
+void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
+ const Instruction *StartingInst,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
+ SmallVectorImpl<ReturnInst*> &Returns,
+ const char *NameSuffix = "",
+ ClonedCodeInfo *CodeInfo = nullptr,
+ const DataLayout *DL = nullptr,
+ CloningDirector *Director = nullptr);
+
+
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly. The
/// effect of this is to copy significantly less code in cases where (for
@@ -147,8 +180,7 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
/// mappings.
///
void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
- ValueToValueMapTy &VMap,
- bool ModuleLevelChanges,
+ ValueToValueMapTy &VMap, bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix = "",
ClonedCodeInfo *CodeInfo = nullptr,
@@ -162,19 +194,19 @@ public:
explicit InlineFunctionInfo(CallGraph *cg = nullptr,
const DataLayout *DL = nullptr,
AliasAnalysis *AA = nullptr,
- AssumptionTracker *AT = nullptr)
- : CG(cg), DL(DL), AA(AA), AT(AT) {}
+ AssumptionCacheTracker *ACT = nullptr)
+ : CG(cg), DL(DL), AA(AA), ACT(ACT) {}
/// CG - If non-null, InlineFunction will update the callgraph to reflect the
/// changes it makes.
CallGraph *CG;
const DataLayout *DL;
AliasAnalysis *AA;
- AssumptionTracker *AT;
+ AssumptionCacheTracker *ACT;
/// StaticAllocas - InlineFunction fills this in with all static allocas that
/// get copied into the caller.
- SmallVector<AllocaInst*, 4> StaticAllocas;
+ SmallVector<AllocaInst *, 4> StaticAllocas;
/// InlinedCalls - InlineFunction fills this in with callsites that were
/// inlined from the callee. This is only filled in if CG is non-null.
@@ -196,9 +228,12 @@ public:
/// exists in the instruction stream. Similarly this will inline a recursive
/// function by one level.
///
-bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, bool InsertLifetime = true);
-bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InsertLifetime = true);
-bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime = true);
+bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
+bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
+bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
+ bool InsertLifetime = true);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index e89e5e5..463ab96 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -31,10 +31,9 @@ class DbgDeclareInst;
class StoreInst;
class LoadInst;
class Value;
-class Pass;
class PHINode;
class AllocaInst;
-class AssumptionTracker;
+class AssumptionCache;
class ConstantExpr;
class DataLayout;
class TargetLibraryInfo;
@@ -115,7 +114,7 @@ void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
/// between them, moving the instructions in the predecessor into BB. This
/// deletes the predecessor block.
///
-void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = nullptr);
+void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr);
/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an
/// unconditional branch, and contains no instructions other than PHI nodes,
@@ -138,9 +137,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB);
/// the basic block that was pointed to.
///
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
- unsigned BonusInstThreshold,
- const DataLayout *TD = nullptr,
- AssumptionTracker *AT = nullptr);
+ unsigned BonusInstThreshold, const DataLayout *TD = nullptr,
+ AssumptionCache *AC = nullptr);
/// FlatternCFG - This function is used to flatten a CFG. For
/// example, it uses parallel-and and parallel-or mode to collapse
@@ -176,17 +174,17 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr);
/// increase the alignment of the ultimate object, making this check succeed.
unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
const DataLayout *TD = nullptr,
- AssumptionTracker *AT = nullptr,
+ AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
/// getKnownAlignment - Try to infer an alignment for the specified pointer.
static inline unsigned getKnownAlignment(Value *V,
const DataLayout *TD = nullptr,
- AssumptionTracker *AT = nullptr,
+ AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr) {
- return getOrEnforceKnownAlignment(V, 0, TD, AT, CxtI, DT);
+ return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT);
}
/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
@@ -276,10 +274,11 @@ bool LowerDbgDeclare(Function &F);
/// an alloca, if any.
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
-/// replaceDbgDeclareForAlloca - Replaces llvm.dbg.declare instruction when
-/// alloca is replaced with a new value.
+/// \brief Replaces llvm.dbg.declare instruction when an alloca is replaced with
+/// a new value. If Deref is true, tan additional DW_OP_deref is prepended to
+/// the expression.
bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
- DIBuilder &Builder);
+ DIBuilder &Builder, bool Deref);
/// \brief Remove all blocks that can not be reached from the function's entry.
///
diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h
index fdae80d..bb80f20 100644
--- a/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/include/llvm/Transforms/Utils/LoopUtils.h
@@ -14,16 +14,33 @@
#ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
#define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Dominators.h"
+
namespace llvm {
class AliasAnalysis;
-class AssumptionTracker;
+class AliasSet;
+class AliasSetTracker;
+class AssumptionCache;
class BasicBlock;
class DataLayout;
class DominatorTree;
class Loop;
class LoopInfo;
class Pass;
+class PredIteratorCache;
class ScalarEvolution;
+class TargetLibraryInfo;
+
+/// \brief Captures loop safety information.
+/// It keep information for loop & its header may throw exception.
+struct LICMSafetyInfo {
+ bool MayThrow; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow; // Same as previous, but specific to loop header
+ LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false)
+ {}
+};
BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);
@@ -36,7 +53,7 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);
bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP,
AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr,
const DataLayout *DL = nullptr,
- AssumptionTracker *AT = nullptr);
+ AssumptionCache *AC = nullptr);
/// \brief Put loop into LCSSA form.
///
@@ -49,7 +66,8 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP,
/// If ScalarEvolution is passed in, it will be preserved.
///
/// Returns true if any modifications are made to the loop.
-bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr);
+bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
+ ScalarEvolution *SE = nullptr);
/// \brief Put a loop nest into LCSSA form.
///
@@ -60,8 +78,51 @@ bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr);
/// If ScalarEvolution is passed in, it will be preserved.
///
/// Returns true if any modifications are made to the loop.
-bool formLCSSARecursively(Loop &L, DominatorTree &DT,
+bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
ScalarEvolution *SE = nullptr);
+
+/// \brief Walk the specified region of the CFG (defined by all blocks
+/// dominated by the specified block, and that are in the current loop) in
+/// reverse depth first order w.r.t the DominatorTree. This allows us to visit
+/// uses before definitions, allowing us to sink a loop body in one pass without
+/// iteration. Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree,
+/// DataLayout, TargetLibraryInfo, Loop, AliasSet information for all
+/// instructions of the loop and loop safety information as arguments.
+/// It returns changed status.
+bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
+ const DataLayout *, TargetLibraryInfo *, Loop *,
+ AliasSetTracker *, LICMSafetyInfo *);
+
+/// \brief Walk the specified region of the CFG (defined by all blocks
+/// dominated by the specified block, and that are in the current loop) in depth
+/// first order w.r.t the DominatorTree. This allows us to visit definitions
+/// before uses, allowing us to hoist a loop body in one pass without iteration.
+/// Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, DataLayout,
+/// TargetLibraryInfo, Loop, AliasSet information for all instructions of the
+/// loop and loop safety information as arguments. It returns changed status.
+bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
+ const DataLayout *, TargetLibraryInfo *, Loop *,
+ AliasSetTracker *, LICMSafetyInfo *);
+
+/// \brief Try to promote memory values to scalars by sinking stores out of
+/// the loop and moving loads to before the loop. We do this by looping over
+/// the stores in the loop, looking for stores to Must pointers which are
+/// loop invariant. It takes AliasSet, Loop exit blocks vector, loop exit blocks
+/// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop,
+/// AliasSet information for all instructions of the loop and loop safety
+/// information as arguments. It returns changed status.
+bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &,
+ SmallVectorImpl<Instruction*> &,
+ PredIteratorCache &, LoopInfo *,
+ DominatorTree *, Loop *, AliasSetTracker *,
+ LICMSafetyInfo *);
+
+/// \brief Computes safety information for a loop
+/// checks loop body & header for the possiblity of may throw
+/// exception, it takes LICMSafetyInfo and loop as argument.
+/// Updates safety information in LICMSafetyInfo argument.
+void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *);
+
}
#endif
diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h
index 3fdd5e9..d0602bf 100644
--- a/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -22,7 +22,7 @@ namespace llvm {
class AllocaInst;
class DominatorTree;
class AliasSetTracker;
-class AssumptionTracker;
+class AssumptionCache;
/// \brief Return true if this alloca is legal for promotion.
///
@@ -43,7 +43,7 @@ bool isAllocaPromotable(const AllocaInst *AI);
/// made to the IR.
void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
AliasSetTracker *AST = nullptr,
- AssumptionTracker *AT = nullptr);
+ AssumptionCache *AC = nullptr);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index 7874a5f..19e2a4a 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -118,8 +118,8 @@ public:
private:
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
- void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION;
- SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION;
+ void operator=(const SSAUpdater&) = delete;
+ SSAUpdater(const SSAUpdater&) = delete;
};
/// \brief Helper class for promoting a collection of loads and stores into SSA
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 6765ac1..08358e1 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -16,6 +16,7 @@
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm {
@@ -27,20 +28,67 @@ class TargetLibraryInfo;
class BasicBlock;
class Function;
+/// \brief This class implements simplifications for calls to fortified library
+/// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to,
+/// when possible, replace them with their non-checking counterparts.
+/// Other optimizations can also be done, but it's possible to disable them and
+/// only simplify needless use of the checking versions (when the object size
+/// is unknown) by passing true for OnlyLowerUnknownSize.
+class FortifiedLibCallSimplifier {
+private:
+ const DataLayout *DL;
+ const TargetLibraryInfo *TLI;
+ bool OnlyLowerUnknownSize;
+
+public:
+ FortifiedLibCallSimplifier(const DataLayout *DL, const TargetLibraryInfo *TLI,
+ bool OnlyLowerUnknownSize = false);
+
+ /// \brief Take the given call instruction and return a more
+ /// optimal value to replace the instruction with or 0 if a more
+ /// optimal form can't be found.
+ /// The call must not be an indirect call.
+ Value *optimizeCall(CallInst *CI);
+
+private:
+ Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B);
+ Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);
+
+ // Str/Stp cpy are similar enough to be handled in the same functions.
+ Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func);
+ Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func);
+
+ /// \brief Checks whether the call \p CI to a fortified libcall is foldable
+ /// to the non-fortified version.
+ bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp,
+ unsigned SizeOp, bool isString);
+};
+
/// LibCallSimplifier - This class implements a collection of optimizations
/// that replace well formed calls to library functions with a more optimal
/// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'.
class LibCallSimplifier {
private:
+ FortifiedLibCallSimplifier FortifiedSimplifier;
const DataLayout *DL;
const TargetLibraryInfo *TLI;
bool UnsafeFPShrink;
+ function_ref<void(Instruction *, Value *)> Replacer;
+
+ /// \brief Internal wrapper for RAUW that is the default implementation.
+ ///
+ /// Other users may provide an alternate function with this signature instead
+ /// of this one.
+ static void replaceAllUsesWithDefault(Instruction *I, Value *With);
-protected:
- ~LibCallSimplifier() {}
+ /// \brief Replace an instruction's uses with a value using our replacer.
+ void replaceAllUsesWith(Instruction *I, Value *With);
public:
- LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI);
+ LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI,
+ function_ref<void(Instruction *, Value *)> Replacer =
+ &replaceAllUsesWithDefault);
/// optimizeCall - Take the given call instruction and return a more
/// optimal value to replace the instruction with or 0 if a more
@@ -48,22 +96,10 @@ public:
/// be equal to the instruction being optimized. In this case all
/// other instructions that use the given instruction were modified
/// and the given instruction is dead.
+ /// The call must not be an indirect call.
Value *optimizeCall(CallInst *CI);
- /// replaceAllUsesWith - This method is used when the library call
- /// simplifier needs to replace instructions other than the library
- /// call being modified.
- virtual void replaceAllUsesWith(Instruction *I, Value *With) const;
-
private:
- // Fortified Library Call Optimizations
- Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B);
- Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B);
- Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);
- Value *optimizeStrCpyChk(CallInst *CI, IRBuilder<> &B);
- Value *optimizeStpCpyChk(CallInst *CI, IRBuilder<> &B);
- Value *optimizeStrNCpyChk(CallInst *CI, IRBuilder<> &B);
-
// String and Memory Library Call Optimizations
Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B);
Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B);
@@ -84,6 +120,8 @@ private:
Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
+ // Wrapper for all String/Memory Library Call Optimizations
+ Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);
// Math Library Optimizations
Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool CheckRetType);
diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h
index af79372..48dea04 100644
--- a/include/llvm/Transforms/Utils/SymbolRewriter.h
+++ b/include/llvm/Transforms/Utils/SymbolRewriter.h
@@ -60,10 +60,10 @@ namespace SymbolRewriter {
/// select the symbols to rewrite. This descriptor list is passed to the
/// SymbolRewriter pass.
class RewriteDescriptor : public ilist_node<RewriteDescriptor> {
- RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+ RewriteDescriptor(const RewriteDescriptor &) = delete;
const RewriteDescriptor &
- operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
+ operator=(const RewriteDescriptor &) = delete;
public:
enum class Type {
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index 0b88d25..04d9ee1 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -16,20 +16,25 @@
#ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
#define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H
+#include "llvm/ADT/StringRef.h"
+
namespace llvm {
-class AssumptionTracker;
+class AssumptionCache;
class Loop;
class LoopInfo;
class LPPassManager;
+class MDNode;
class Pass;
bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,
unsigned TripMultiple, LoopInfo *LI, Pass *PP,
- LPPassManager *LPM, AssumptionTracker *AT);
+ LPPassManager *LPM, AssumptionCache *AC);
bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
LPPassManager* LPM);
+
+MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
}
#endif
diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h
index 5774763..047ab81 100644
--- a/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/include/llvm/Transforms/Utils/ValueMapper.h
@@ -71,20 +71,23 @@ namespace llvm {
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+ Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
+ /// MapMetadata - provide versions that preserve type safety for MDNodes.
+ MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
- /// MapValue - provide versions that preserve type safety for MDNode and
- /// Constants.
- inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr) {
- return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper,
- Materializer));
- }
+ /// MapValue - provide versions that preserve type safety for Constants.
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h
index 83871fc..9f0fb19 100644
--- a/include/llvm/Transforms/Utils/VectorUtils.h
+++ b/include/llvm/Transforms/Utils/VectorUtils.h
@@ -14,9 +14,9 @@
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
-#include "llvm/IR/Intrinsics.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/Target/TargetLibraryInfo.h"
+#include "llvm/IR/Intrinsics.h"
namespace llvm {
@@ -59,7 +59,7 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) {
}
}
-static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
+static inline bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
unsigned ScalarOpdIdx) {
switch (ID) {
case Intrinsic::ctlz:
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index 46f6e40..0f9c22e 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -40,7 +40,43 @@ module LLVM_Backend {
module LLVM_Bitcode { requires cplusplus umbrella "Bitcode" module * { export * } }
module LLVM_Config { requires cplusplus umbrella "Config" module * { export * } }
-module LLVM_DebugInfo { requires cplusplus umbrella "DebugInfo" module * { export * } }
+
+module LLVM_DebugInfo_DWARF {
+ requires cplusplus
+
+ umbrella "DebugInfo/DWARF"
+ module * { export * }
+}
+
+module LLVM_DebugInfo_PDB {
+ requires cplusplus
+
+ umbrella "DebugInfo/PDB"
+ module * { export * }
+
+ // Separate out this subdirectory; it's an optional component that depends on
+ // a separate library which might not be available.
+ //
+ // FIXME: There should be a better way to specify this.
+ exclude header "DebugInfo/PDB/DIA/DIADataStream.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+ exclude header "DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+ exclude header "DebugInfo/PDB/DIA/DIALineNumber.h"
+ exclude header "DebugInfo/PDB/DIA/DIARawSymbol.h"
+ exclude header "DebugInfo/PDB/DIA/DIASession.h"
+ exclude header "DebugInfo/PDB/DIA/DIASourceFile.h"
+ exclude header "DebugInfo/PDB/DIA/DIASupport.h"
+}
+
+module LLVM_DebugInfo_PDB_DIA {
+ requires cplusplus
+
+ umbrella "DebugInfo/PDB/DIA"
+ module * { export * }
+}
+
module LLVM_ExecutionEngine {
requires cplusplus
@@ -55,6 +91,7 @@ module LLVM_ExecutionEngine {
exclude header "ExecutionEngine/JIT.h"
exclude header "ExecutionEngine/MCJIT.h"
exclude header "ExecutionEngine/Interpreter.h"
+ exclude header "ExecutionEngine/OrcMCJITReplacement.h"
}
module LLVM_IR {
@@ -70,26 +107,10 @@ module LLVM_IR {
umbrella "IR"
module * { export * }
- // We cannot have llvm/PassManager.h and llvm/IR/PassManager.h in the same TU,
- // so we can't include llvm/IR/PassManager.h in the IR module.
- exclude header "IR/PassManager.h"
- exclude header "IR/LegacyPassManager.h"
-
- // Exclude this; it's intended for (repeated) textual inclusion.
- exclude header "IR/Instruction.def"
-}
-
-module LLVM_LegacyPassManager {
- requires cplusplus
- module CompatInterface { header "PassManager.h" export * }
- module Implementation { header "IR/LegacyPassManager.h" export * }
-}
-
-module LLVM_IR_PassManager {
- requires cplusplus
- // FIXME PR19358: This doesn't work! conflict LLVM_LegacyPassManager, "cannot use legacy pass manager and new pass manager in same file"
- header "IR/PassManager.h"
- export *
+ // These are intended for (repeated) textual inclusion.
+ textual header "IR/DebugInfoFlags.def"
+ textual header "IR/Instruction.def"
+ textual header "IR/Metadata.def"
}
module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } }
@@ -161,6 +182,19 @@ module LLVM_Utils {
// FIXME: Mislayered?
exclude header "Support/TargetRegistry.h"
+
+ // These are intended for textual inclusion.
+ textual header "Support/Dwarf.def"
+ textual header "Support/ELFRelocs/AArch64.def"
+ textual header "Support/ELFRelocs/ARM.def"
+ textual header "Support/ELFRelocs/Hexagon.def"
+ textual header "Support/ELFRelocs/i386.def"
+ textual header "Support/ELFRelocs/Mips.def"
+ textual header "Support/ELFRelocs/PowerPC64.def"
+ textual header "Support/ELFRelocs/PowerPC.def"
+ textual header "Support/ELFRelocs/Sparc.def"
+ textual header "Support/ELFRelocs/SystemZ.def"
+ textual header "Support/ELFRelocs/x86_64.def"
}
}